Merge pull request #3065 from yang-g/string_ref

Use string_ref for incoming metadata
diff --git a/BUILD b/BUILD
index 25b26b7..d612d9c 100644
--- a/BUILD
+++ b/BUILD
@@ -51,6 +51,7 @@
     "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/alloc.c",
     "src/core/support/cmdline.c",
     "src/core/support/cpu_iphone.c",
@@ -208,7 +209,6 @@
     "src/core/json/json_reader.h",
     "src/core/json/json_writer.h",
     "src/core/profiling/timers.h",
-    "src/core/profiling/timers_preciseclock.h",
     "src/core/statistics/census_interface.h",
     "src/core/statistics/census_rpc_stats.h",
     "src/core/surface/byte_buffer_queue.h",
@@ -477,7 +477,6 @@
     "src/core/json/json_reader.h",
     "src/core/json/json_writer.h",
     "src/core/profiling/timers.h",
-    "src/core/profiling/timers_preciseclock.h",
     "src/core/statistics/census_interface.h",
     "src/core/statistics/census_rpc_stats.h",
     "src/core/surface/byte_buffer_queue.h",
@@ -992,6 +991,7 @@
     "src/core/support/string.h",
     "src/core/support/string_win32.h",
     "src/core/support/thd_internal.h",
+    "src/core/support/time_precise.h",
   ],
   includes = [
     "include",
@@ -1232,7 +1232,6 @@
     "src/core/json/json_reader.h",
     "src/core/json/json_writer.h",
     "src/core/profiling/timers.h",
-    "src/core/profiling/timers_preciseclock.h",
     "src/core/statistics/census_interface.h",
     "src/core/statistics/census_rpc_stats.h",
     "src/core/surface/byte_buffer_queue.h",
diff --git a/Makefile b/Makefile
index 77cb620..f902cfc 100644
--- a/Makefile
+++ b/Makefile
@@ -791,6 +791,7 @@
 fling_stream_test: $(BINDIR)/$(CONFIG)/fling_stream_test
 fling_test: $(BINDIR)/$(CONFIG)/fling_test
 gen_hpack_tables: $(BINDIR)/$(CONFIG)/gen_hpack_tables
+gen_legal_metadata_characters: $(BINDIR)/$(CONFIG)/gen_legal_metadata_characters
 gpr_cmdline_test: $(BINDIR)/$(CONFIG)/gpr_cmdline_test
 gpr_env_test: $(BINDIR)/$(CONFIG)/gpr_env_test
 gpr_file_test: $(BINDIR)/$(CONFIG)/gpr_file_test
@@ -1650,8 +1651,8 @@
 	$(Q)(cd third_party/openssl ; CC="$(CC) $(PIC_CPPFLAGS) -fvisibility=hidden $(CPPFLAGS_$(CONFIG)) $(OPENSSL_CFLAGS_$(CONFIG)) $(OPENSSL_CFLAGS_EXTRA)" ./config no-asm $(OPENSSL_CONFIG_$(CONFIG)))
 endif
 endif
-	$(Q)$(MAKE) -C third_party/openssl clean
-	$(Q)(unset CPPFLAGS; $(MAKE) -C third_party/openssl build_crypto build_ssl)
+	$(Q)$(MAKE) -j 1 -C third_party/openssl clean
+	$(Q)(unset CPPFLAGS; $(MAKE) -j 1 -C third_party/openssl build_crypto build_ssl)
 	$(Q)mkdir -p $(LIBDIR)/$(CONFIG)/openssl
 	$(Q)cp third_party/openssl/libssl.a third_party/openssl/libcrypto.a $(LIBDIR)/$(CONFIG)/openssl
 
@@ -3384,7 +3385,7 @@
 tools: tools_c tools_cxx
 
 
-tools_c: privatelibs_c $(BINDIR)/$(CONFIG)/gen_hpack_tables $(BINDIR)/$(CONFIG)/grpc_create_jwt $(BINDIR)/$(CONFIG)/grpc_fetch_oauth2 $(BINDIR)/$(CONFIG)/grpc_print_google_default_creds_token $(BINDIR)/$(CONFIG)/grpc_verify_jwt
+tools_c: privatelibs_c $(BINDIR)/$(CONFIG)/gen_hpack_tables $(BINDIR)/$(CONFIG)/gen_legal_metadata_characters $(BINDIR)/$(CONFIG)/grpc_create_jwt $(BINDIR)/$(CONFIG)/grpc_fetch_oauth2 $(BINDIR)/$(CONFIG)/grpc_print_google_default_creds_token $(BINDIR)/$(CONFIG)/grpc_verify_jwt
 
 tools_cxx: privatelibs_cxx
 
@@ -7122,6 +7123,35 @@
 endif
 
 
+GEN_LEGAL_METADATA_CHARACTERS_SRC = \
+    tools/codegen/core/gen_legal_metadata_characters.c \
+
+GEN_LEGAL_METADATA_CHARACTERS_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GEN_LEGAL_METADATA_CHARACTERS_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/gen_legal_metadata_characters: openssl_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/gen_legal_metadata_characters: $(GEN_LEGAL_METADATA_CHARACTERS_OBJS)
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS) $(GEN_LEGAL_METADATA_CHARACTERS_OBJS) $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/gen_legal_metadata_characters
+
+endif
+
+$(OBJDIR)/$(CONFIG)/tools/codegen/core/gen_legal_metadata_characters.o: 
+deps_gen_legal_metadata_characters: $(GEN_LEGAL_METADATA_CHARACTERS_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(GEN_LEGAL_METADATA_CHARACTERS_OBJS:.o=.dep)
+endif
+endif
+
+
 GPR_CMDLINE_TEST_SRC = \
     test/core/support/cmdline_test.c \
 
diff --git a/build.json b/build.json
index c974250..bee0983 100644
--- a/build.json
+++ b/build.json
@@ -181,7 +181,6 @@
         "src/core/json/json_reader.h",
         "src/core/json/json_writer.h",
         "src/core/profiling/timers.h",
-        "src/core/profiling/timers_preciseclock.h",
         "src/core/statistics/census_interface.h",
         "src/core/statistics/census_rpc_stats.h",
         "src/core/surface/byte_buffer_queue.h",
@@ -404,7 +403,8 @@
         "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/thd_internal.h",
+        "src/core/support/time_precise.h"
       ],
       "src": [
         "src/core/support/alloc.c",
@@ -1151,6 +1151,15 @@
       ]
     },
     {
+      "name": "gen_legal_metadata_characters",
+      "build": "tool",
+      "language": "c",
+      "src": [
+        "tools/codegen/core/gen_legal_metadata_characters.c"
+      ],
+      "deps": []
+    },
+    {
       "name": "gpr_cmdline_test",
       "build": "test",
       "language": "c",
diff --git a/gRPC.podspec b/gRPC.podspec
index f6d09db..55f72c9 100644
--- a/gRPC.podspec
+++ b/gRPC.podspec
@@ -68,6 +68,7 @@
                       'src/core/support/grpc_string.h',
                       'src/core/support/string_win32.h',
                       'src/core/support/thd_internal.h',
+                      'src/core/support/time_precise.h',
                       'grpc/support/alloc.h',
                       'grpc/support/atm.h',
                       'grpc/support/atm_gcc_atomic.h',
@@ -210,7 +211,6 @@
                       'src/core/json/json_reader.h',
                       'src/core/json/json_writer.h',
                       'src/core/profiling/timers.h',
-                      'src/core/profiling/timers_preciseclock.h',
                       'src/core/statistics/census_interface.h',
                       'src/core/statistics/census_rpc_stats.h',
                       'src/core/surface/byte_buffer_queue.h',
@@ -404,6 +404,7 @@
                               '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/security/auth_filters.h',
                               'src/core/security/base64.h',
                               'src/core/security/credentials.h',
@@ -482,7 +483,6 @@
                               'src/core/json/json_reader.h',
                               'src/core/json/json_writer.h',
                               'src/core/profiling/timers.h',
-                              'src/core/profiling/timers_preciseclock.h',
                               'src/core/statistics/census_interface.h',
                               'src/core/statistics/census_rpc_stats.h',
                               'src/core/surface/byte_buffer_queue.h',
diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h
index 101fc88..145052b 100644
--- a/include/grpc/grpc.h
+++ b/include/grpc/grpc.h
@@ -134,6 +134,14 @@
 /** 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 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.
+   If this argument is not specified, the name used for SSL host name checking
+   will be the target parameter (assuming that the secure channel is an SSL
+   channel). If this parameter is specified and the underlying is not an SSL
+   channel, it will just be ignored. */
+#define GRPC_SSL_TARGET_NAME_OVERRIDE_ARG "grpc.ssl_target_name_override"
 
 /** Connectivity state of a channel. */
 typedef enum {
diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h
index 7f8f4d4..de565b2 100644
--- a/include/grpc/grpc_security.h
+++ b/include/grpc/grpc_security.h
@@ -142,15 +142,6 @@
 
 /* --- Secure channel creation. --- */
 
-/* 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.
-   If this argument is not specified, the name used for SSL host name checking
-   will be the target parameter (assuming that the secure channel is an SSL
-   channel). If this parameter is specified and the underlying is not an SSL
-   channel, it will just be ignored. */
-#define GRPC_SSL_TARGET_NAME_OVERRIDE_ARG "grpc.ssl_target_name_override"
-
 /* Creates a secure channel using the passed-in credentials. */
 grpc_channel *grpc_secure_channel_create(grpc_credentials *creds,
                                          const char *target,
diff --git a/include/grpc/support/time.h b/include/grpc/support/time.h
index 4ef9c76..f8ed893 100644
--- a/include/grpc/support/time.h
+++ b/include/grpc/support/time.h
@@ -52,6 +52,9 @@
   /* Realtime clock. May jump forwards or backwards. Settable by
      the system administrator. Has its epoch at 0:00:00 UTC 1 Jan 1970. */
   GPR_CLOCK_REALTIME,
+  /* CPU cycle time obtained by rdtsc instruction on x86 platforms. Epoch
+     undefined. Degrades to GPR_CLOCK_REALTIME on other platforms. */
+  GPR_CLOCK_PRECISE,
   /* Unmeasurable clock type: no base, created by taking the difference
      between two times */
   GPR_TIMESPAN
diff --git a/src/core/channel/compress_filter.h b/src/core/channel/compress_filter.h
index 0917e81..415459b 100644
--- a/src/core/channel/compress_filter.h
+++ b/src/core/channel/compress_filter.h
@@ -36,7 +36,7 @@
 
 #include "src/core/channel/channel_stack.h"
 
-#define GRPC_COMPRESS_REQUEST_ALGORITHM_KEY "internal:grpc-encoding-request"
+#define GRPC_COMPRESS_REQUEST_ALGORITHM_KEY "grpc-internal-encoding-request"
 
 /** Compression filter for outgoing data.
  *
diff --git a/src/core/channel/http_client_filter.c b/src/core/channel/http_client_filter.c
index 48c623d..2b61d33 100644
--- a/src/core/channel/http_client_filter.c
+++ b/src/core/channel/http_client_filter.c
@@ -45,7 +45,6 @@
   grpc_linked_mdelem content_type;
   grpc_linked_mdelem user_agent;
   int sent_initial_metadata;
-  int sent_authority;
 
   int got_initial_metadata;
   grpc_stream_op_buffer *recv_ops;
@@ -64,7 +63,6 @@
   grpc_mdelem *scheme;
   grpc_mdelem *content_type;
   grpc_mdelem *status;
-  grpc_mdelem *default_authority;
   /** complete user agent mdelem */
   grpc_mdelem *user_agent;
 } channel_data;
@@ -103,7 +101,6 @@
 
 static grpc_mdelem *client_strip_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;
   /* eat the things we'd like to set ourselves */
   if (md->key == channeld->method->key) return NULL;
@@ -111,10 +108,6 @@
   if (md->key == channeld->te_trailers->key) return NULL;
   if (md->key == channeld->content_type->key) return NULL;
   if (md->key == channeld->user_agent->key) return NULL;
-  if (channeld->default_authority &&
-      channeld->default_authority->key == md->key) {
-    calld->sent_authority = 1;
-  }
   return md;
 }
 
@@ -138,11 +131,6 @@
                                    GRPC_MDELEM_REF(channeld->method));
       grpc_metadata_batch_add_head(&op->data.metadata, &calld->scheme,
                                    GRPC_MDELEM_REF(channeld->scheme));
-      if (channeld->default_authority && !calld->sent_authority) {
-        grpc_metadata_batch_add_head(
-            &op->data.metadata, &calld->authority,
-            GRPC_MDELEM_REF(channeld->default_authority));
-      }
       grpc_metadata_batch_add_tail(&op->data.metadata, &calld->te_trailers,
                                    GRPC_MDELEM_REF(channeld->te_trailers));
       grpc_metadata_batch_add_tail(&op->data.metadata, &calld->content_type,
@@ -175,7 +163,6 @@
   call_data *calld = elem->call_data;
   calld->sent_initial_metadata = 0;
   calld->got_initial_metadata = 0;
-  calld->sent_authority = 0;
   calld->on_done_recv = NULL;
   grpc_iomgr_closure_init(&calld->hc_on_recv, hc_on_recv, elem);
   if (initial_op) hc_mutate_op(elem, initial_op);
@@ -257,8 +244,6 @@
 static void init_channel_elem(grpc_channel_element *elem, grpc_channel *master,
                               const grpc_channel_args *channel_args,
                               grpc_mdctx *mdctx, int is_first, int is_last) {
-  size_t i;
-
   /* grab pointers to our data from the channel element */
   channel_data *channeld = elem->channel_data;
 
@@ -267,21 +252,6 @@
      path */
   GPR_ASSERT(!is_last);
 
-  channeld->default_authority = NULL;
-  if (channel_args) {
-    for (i = 0; i < channel_args->num_args; i++) {
-      if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_DEFAULT_AUTHORITY)) {
-        if (channel_args->args[i].type != GRPC_ARG_STRING) {
-          gpr_log(GPR_ERROR, "%s: must be an string",
-                  GRPC_ARG_DEFAULT_AUTHORITY);
-        } else {
-          channeld->default_authority = grpc_mdelem_from_strings(
-              mdctx, ":authority", channel_args->args[i].value.string);
-        }
-      }
-    }
-  }
-
   /* initialize members */
   channeld->te_trailers = grpc_mdelem_from_strings(mdctx, "te", "trailers");
   channeld->method = grpc_mdelem_from_strings(mdctx, ":method", "POST");
@@ -306,9 +276,6 @@
   GRPC_MDELEM_UNREF(channeld->content_type);
   GRPC_MDELEM_UNREF(channeld->status);
   GRPC_MDELEM_UNREF(channeld->user_agent);
-  if (channeld->default_authority) {
-    GRPC_MDELEM_UNREF(channeld->default_authority);
-  }
 }
 
 const grpc_channel_filter grpc_http_client_filter = {
diff --git a/src/core/client_config/resolver_factory.c b/src/core/client_config/resolver_factory.c
index 6721977..5b859a8 100644
--- a/src/core/client_config/resolver_factory.c
+++ b/src/core/client_config/resolver_factory.c
@@ -45,6 +45,12 @@
 grpc_resolver *grpc_resolver_factory_create_resolver(
     grpc_resolver_factory *factory, grpc_uri *uri,
     grpc_subchannel_factory *subchannel_factory) {
-  if (!factory) return NULL;
+  if (factory == NULL) return NULL;
   return factory->vtable->create_resolver(factory, uri, subchannel_factory);
 }
+
+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
index c5d8549..e243b23 100644
--- a/src/core/client_config/resolver_factory.h
+++ b/src/core/client_config/resolver_factory.h
@@ -51,9 +51,16 @@
   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_uri *uri,
       grpc_subchannel_factory *subchannel_factory);
+
+  /** 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);
@@ -64,4 +71,9 @@
     grpc_resolver_factory *factory, grpc_uri *uri,
     grpc_subchannel_factory *subchannel_factory);
 
+/** 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_INTERNAL_CORE_CONFIG_RESOLVER_FACTORY_H */
diff --git a/src/core/client_config/resolver_registry.c b/src/core/client_config/resolver_registry.c
index 16be2da..37979b3 100644
--- a/src/core/client_config/resolver_registry.c
+++ b/src/core/client_config/resolver_registry.c
@@ -41,41 +41,33 @@
 
 #define MAX_RESOLVERS 10
 
-typedef struct {
-  char *scheme;
-  grpc_resolver_factory *factory;
-} registered_resolver;
-
-static registered_resolver g_all_of_the_resolvers[MAX_RESOLVERS];
+static grpc_resolver_factory *g_all_of_the_resolvers[MAX_RESOLVERS];
 static int g_number_of_resolvers = 0;
 
-static char *g_default_resolver_scheme;
+static char *g_default_resolver_prefix;
 
-void grpc_resolver_registry_init(const char *default_resolver_scheme) {
+void grpc_resolver_registry_init(const char *default_resolver_prefix) {
   g_number_of_resolvers = 0;
-  g_default_resolver_scheme = gpr_strdup(default_resolver_scheme);
+  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++) {
-    gpr_free(g_all_of_the_resolvers[i].scheme);
-    grpc_resolver_factory_unref(g_all_of_the_resolvers[i].factory);
+    grpc_resolver_factory_unref(g_all_of_the_resolvers[i]);
   }
-  gpr_free(g_default_resolver_scheme);
+  gpr_free(g_default_resolver_prefix);
 }
 
-void grpc_register_resolver_type(const char *scheme,
-                                 grpc_resolver_factory *factory) {
+void grpc_register_resolver_type(grpc_resolver_factory *factory) {
   int i;
   for (i = 0; i < g_number_of_resolvers; i++) {
-    GPR_ASSERT(0 != strcmp(scheme, g_all_of_the_resolvers[i].scheme));
+    GPR_ASSERT(0 != strcmp(factory->vtable->scheme,
+                           g_all_of_the_resolvers[i]->vtable->scheme));
   }
   GPR_ASSERT(g_number_of_resolvers != MAX_RESOLVERS);
-  g_all_of_the_resolvers[g_number_of_resolvers].scheme = gpr_strdup(scheme);
   grpc_resolver_factory_ref(factory);
-  g_all_of_the_resolvers[g_number_of_resolvers].factory = factory;
-  g_number_of_resolvers++;
+  g_all_of_the_resolvers[g_number_of_resolvers++] = factory;
 }
 
 static grpc_resolver_factory *lookup_factory(grpc_uri *uri) {
@@ -85,40 +77,57 @@
   if (!uri) return NULL;
 
   for (i = 0; i < g_number_of_resolvers; i++) {
-    if (0 == strcmp(uri->scheme, g_all_of_the_resolvers[i].scheme)) {
-      return g_all_of_the_resolvers[i].factory;
+    if (0 == strcmp(uri->scheme, g_all_of_the_resolvers[i]->vtable->scheme)) {
+      return g_all_of_the_resolvers[i];
     }
   }
 
   return NULL;
 }
 
-grpc_resolver *grpc_resolver_create(
-    const char *name, grpc_subchannel_factory *subchannel_factory) {
-  grpc_uri *uri;
+static grpc_resolver_factory *resolve_factory(const char *target,
+                                              grpc_uri **uri) {
   char *tmp;
   grpc_resolver_factory *factory = NULL;
-  grpc_resolver *resolver;
 
-  uri = grpc_uri_parse(name, 1);
-  factory = lookup_factory(uri);
-  if (factory == NULL && g_default_resolver_scheme != NULL) {
-    grpc_uri_destroy(uri);
-    gpr_asprintf(&tmp, "%s%s", g_default_resolver_scheme, name);
-    uri = grpc_uri_parse(tmp, 1);
-    factory = lookup_factory(uri);
-    if (factory == NULL) {
-      grpc_uri_destroy(grpc_uri_parse(name, 0));
-      grpc_uri_destroy(grpc_uri_parse(tmp, 0));
-      gpr_log(GPR_ERROR, "don't know how to resolve '%s' or '%s'", name, tmp);
+  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);
     }
-    gpr_free(tmp);
-  } else if (factory == NULL) {
-    grpc_uri_destroy(grpc_uri_parse(name, 0));
-    gpr_log(GPR_ERROR, "don't know how to resolve '%s'", name);
   }
-  resolver =
+  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_factory_create_resolver(factory, uri, subchannel_factory);
   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
index 31aa476..5a7193b 100644
--- a/src/core/client_config/resolver_registry.h
+++ b/src/core/client_config/resolver_registry.h
@@ -44,19 +44,22 @@
     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(const char *scheme,
-                                 grpc_resolver_factory *factory);
+void grpc_register_resolver_type(grpc_resolver_factory *factory);
 
-/** Create a resolver given \a name.
-    First tries to parse \a name as a URI. If this succeeds, tries
+/** 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 name, and tries again (if default_prefix
+    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 *name, grpc_subchannel_factory *subchannel_factory);
+    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_INTERNAL_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
index 7b35b79..84643c4 100644
--- a/src/core/client_config/resolvers/dns_resolver.c
+++ b/src/core/client_config/resolvers/dns_resolver.c
@@ -203,9 +203,6 @@
     grpc_subchannel_factory *subchannel_factory) {
   dns_resolver *r;
   const char *path = uri->path;
-  grpc_arg default_host_arg;
-  char *host;
-  char *port;
 
   if (0 != strcmp(uri->authority, "")) {
     gpr_log(GPR_ERROR, "authority based uri's not supported");
@@ -214,17 +211,6 @@
 
   if (path[0] == '/') ++path;
 
-  gpr_split_host_port(path, &host, &port);
-
-  default_host_arg.type = GRPC_ARG_STRING;
-  default_host_arg.key = GRPC_ARG_DEFAULT_AUTHORITY;
-  default_host_arg.value.string = host;
-  subchannel_factory = grpc_subchannel_factory_add_channel_arg(
-      subchannel_factory, &default_host_arg);
-
-  gpr_free(host);
-  gpr_free(port);
-
   r = gpr_malloc(sizeof(dns_resolver));
   memset(r, 0, sizeof(*r));
   gpr_ref_init(&r->refs, 1);
@@ -233,6 +219,7 @@
   r->name = gpr_strdup(path);
   r->default_port = gpr_strdup(default_port);
   r->subchannel_factory = subchannel_factory;
+  grpc_subchannel_factory_ref(subchannel_factory);
   r->lb_policy_factory = lb_policy_factory;
   return &r->base;
 }
@@ -252,8 +239,16 @@
                     subchannel_factory);
 }
 
+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_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() {
diff --git a/src/core/client_config/resolvers/sockaddr_resolver.c b/src/core/client_config/resolvers/sockaddr_resolver.c
index 8419873..0d8540a 100644
--- a/src/core/client_config/resolvers/sockaddr_resolver.c
+++ b/src/core/client_config/resolvers/sockaddr_resolver.c
@@ -166,8 +166,29 @@
 
   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, int *len) {
   const char *host_port = uri->path;
   char *host;
@@ -313,20 +334,20 @@
 
 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_uri *uri,                  \
-      grpc_subchannel_factory *subchannel_factory) {                  \
-    return sockaddr_create(uri, grpc_create_pick_first_lb_policy,     \
-                           subchannel_factory, parse_##name);         \
-  }                                                                   \
-  static const grpc_resolver_factory_vtable name##_factory_vtable = { \
-      sockaddr_factory_ref, sockaddr_factory_unref,                   \
-      name##_factory_create_resolver};                                \
-  static grpc_resolver_factory name##_resolver_factory = {            \
-      &name##_factory_vtable};                                        \
-  grpc_resolver_factory *grpc_##name##_resolver_factory_create() {    \
-    return &name##_resolver_factory;                                  \
+#define DECL_FACTORY(name)                                                  \
+  static grpc_resolver *name##_factory_create_resolver(                     \
+      grpc_resolver_factory *factory, grpc_uri *uri,                        \
+      grpc_subchannel_factory *subchannel_factory) {                        \
+    return sockaddr_create(uri, grpc_create_pick_first_lb_policy,           \
+                           subchannel_factory, 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
diff --git a/src/core/client_config/resolvers/zookeeper_resolver.c b/src/core/client_config/resolvers/zookeeper_resolver.c
index acb2ba1..da399f9 100644
--- a/src/core/client_config/resolvers/zookeeper_resolver.c
+++ b/src/core/client_config/resolvers/zookeeper_resolver.c
@@ -467,8 +467,7 @@
 }
 
 static void zookeeper_plugin_init() {
-  grpc_register_resolver_type("zookeeper",
-                              grpc_zookeeper_resolver_factory_create());
+  grpc_register_resolver_type(grpc_zookeeper_resolver_factory_create());
 }
 
 void grpc_zookeeper_register() {
@@ -483,6 +482,11 @@
 
 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_uri *uri,
     grpc_subchannel_factory *subchannel_factory) {
@@ -492,7 +496,8 @@
 
 static const grpc_resolver_factory_vtable zookeeper_factory_vtable = {
     zookeeper_factory_ref, zookeeper_factory_unref,
-    zookeeper_factory_create_resolver};
+    zookeeper_factory_create_resolver, zookeeper_factory_get_default_hostname,
+    "zookeeper"};
 static grpc_resolver_factory zookeeper_resolver_factory = {
     &zookeeper_factory_vtable};
 
diff --git a/src/core/profiling/basic_timers.c b/src/core/profiling/basic_timers.c
index ae37f58..4b6a0d2 100644
--- a/src/core/profiling/basic_timers.c
+++ b/src/core/profiling/basic_timers.c
@@ -36,7 +36,6 @@
 #ifdef GRPC_BASIC_PROFILER
 
 #include "src/core/profiling/timers.h"
-#include "src/core/profiling/timers_preciseclock.h"
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
@@ -53,7 +52,7 @@
 } marker_type;
 
 typedef struct grpc_timer_entry {
-  grpc_precise_clock tm;
+  gpr_timespec tm;
   int tag;
   const char* tagstr;
   marker_type type;
@@ -71,9 +70,8 @@
   int i;
   for (i = 0; i < count; i++) {
     grpc_timer_entry* entry = &(log[i]);
-    printf("GRPC_LAT_PROF " GRPC_PRECISE_CLOCK_FORMAT
-           " %p %c %d(%s) %p %s %d\n",
-           GRPC_PRECISE_CLOCK_PRINTF_ARGS(&entry->tm),
+    printf("GRPC_LAT_PROF %ld.%09d  %p %c %d(%s) %p %s %d\n",
+           entry->tm.tv_sec, entry->tm.tv_nsec,
            (void*)(gpr_intptr)gpr_thd_currentid(), entry->type, entry->tag,
            entry->tagstr, entry->id, entry->file, entry->line);
   }
@@ -93,7 +91,7 @@
 
   entry = &log[count++];
 
-  grpc_precise_clock_now(&entry->tm);
+  entry->tm = gpr_now(GPR_CLOCK_PRECISE);
   entry->tag = tag;
   entry->tagstr = tagstr;
   entry->type = type;
diff --git a/src/core/support/time_posix.c b/src/core/support/time_posix.c
index 841485c..a274400 100644
--- a/src/core/support/time_posix.c
+++ b/src/core/support/time_posix.c
@@ -32,6 +32,7 @@
  */
 
 #include <grpc/support/port_platform.h>
+#include <src/core/support/time_precise.h>
 
 #ifdef GPR_POSIX_TIME
 
@@ -66,8 +67,14 @@
 gpr_timespec gpr_now(gpr_clock_type clock) {
   struct timespec now;
   GPR_ASSERT(clock != GPR_TIMESPAN);
-  clock_gettime(clockid_for_gpr_clock[clock], &now);
-  return gpr_from_timespec(now, clock);
+  if (clock == GPR_CLOCK_PRECISE) {
+    gpr_timespec ret;
+    gpr_precise_clock_now(&ret);
+    return ret;
+  } else {
+    clock_gettime(clockid_for_gpr_clock[clock], &now);
+    return gpr_from_timespec(now, clock);
+  }
 }
 #else
 /* For some reason Apple's OSes haven't implemented clock_gettime. */
@@ -104,6 +111,9 @@
       now.tv_sec = now_dbl * 1e-9;
       now.tv_nsec = now_dbl - now.tv_sec * 1e9;
       break;
+    case GPR_CLOCK_PRECISE:
+      gpr_precise_clock_now(&now);
+      break;
     case GPR_TIMESPAN:
       abort();
   }
diff --git a/src/core/profiling/timers_preciseclock.h b/src/core/support/time_precise.h
similarity index 64%
rename from src/core/profiling/timers_preciseclock.h
rename to src/core/support/time_precise.h
index 5c251b4..574ebb8 100644
--- a/src/core/profiling/timers_preciseclock.h
+++ b/src/core/support/time_precise.h
@@ -31,65 +31,63 @@
  *
  */
 
-#ifndef GRPC_CORE_PROFILING_TIMERS_PRECISECLOCK_H
-#define GRPC_CORE_PROFILING_TIMERS_PRECISECLOCK_H
+#ifndef GRPC_CORE_SUPPORT_TIME_PRECISE_H_
+#define GRPC_CORE_SUPPORT_TIME_PRECISE_H_
 
 #include <grpc/support/sync.h>
 #include <grpc/support/time.h>
 #include <stdio.h>
 
 #ifdef GRPC_TIMERS_RDTSC
-typedef long long int grpc_precise_clock;
 #if defined(__i386__)
-static void grpc_precise_clock_now(grpc_precise_clock *clk) {
-  grpc_precise_clock ret;
+static void gpr_get_cycle_counter(long long int *clk) {
+  long long int ret;
   __asm__ volatile("rdtsc" : "=A"(ret));
   *clk = ret;
 }
 
 // ----------------------------------------------------------------
 #elif defined(__x86_64__) || defined(__amd64__)
-static void grpc_precise_clock_now(grpc_precise_clock *clk) {
+static void gpr_get_cycle_counter(long long int *clk) {
   unsigned long long low, high;
   __asm__ volatile("rdtsc" : "=a"(low), "=d"(high));
   *clk = (high << 32) | low;
 }
 #endif
+
 static gpr_once precise_clock_init = GPR_ONCE_INIT;
-static double cycles_per_second = 0.0;
-static void grpc_precise_clock_init() {
+static long long cycles_per_second = 0;
+static void gpr_precise_clock_init() {
   time_t start = time(NULL);
-  grpc_precise_clock start_time;
-  grpc_precise_clock end_time;
+  gpr_precise_clock start_cycle;
+  gpr_precise_clock end_cycle;
   while (time(NULL) == start)
     ;
-  grpc_precise_clock_now(&start_time);
+  gpr_get_cycle_counter(&start_cycle);
   while (time(NULL) == start + 1)
     ;
-  grpc_precise_clock_now(&end_time);
-  cycles_per_second = end_time - start_time;
+  gpr_get_cycle_counter(&end_cycle);
+  cycles_per_second = end_cycle - start_cycle;
 }
+
 static double grpc_precise_clock_scaling_factor() {
   gpr_once_init(&precise_clock_init, grpc_precise_clock_init);
   return 1e6 / cycles_per_second;
 }
-#define GRPC_PRECISE_CLOCK_FORMAT "%f"
-#define GRPC_PRECISE_CLOCK_PRINTF_ARGS(clk) \
-  (*(clk)*grpc_precise_clock_scaling_factor())
-#else
-typedef struct grpc_precise_clock grpc_precise_clock;
-struct grpc_precise_clock {
-  gpr_timespec clock;
-};
-static void grpc_precise_clock_now(grpc_precise_clock* clk) {
-  clk->clock = gpr_now(GPR_CLOCK_REALTIME);
+
+static void gpr_precise_clock_now(gpr_timespec *clk) {
+  long long int counter;
+  gpr_get_cycle_counter(&counter);
+  clk->clock = GPR_CLOCK_REALTIME;
+  clk->tv_sec = counter / cycles_per_second;
+  clk->tv_nsec = counter % cycles_per_second;
 }
-#define GRPC_PRECISE_CLOCK_FORMAT "%ld.%09d"
-#define GRPC_PRECISE_CLOCK_PRINTF_ARGS(clk) \
-  (clk)->clock.tv_sec, (clk)->clock.tv_nsec
-static void grpc_precise_clock_print(const grpc_precise_clock* clk, FILE* fp) {
-  fprintf(fp, "%ld.%09d", clk->clock.tv_sec, clk->clock.tv_nsec);
+
+#else /* GRPC_TIMERS_RDTSC */
+static void gpr_precise_clock_now(gpr_timespec *clk) {
+  *clk = gpr_now(GPR_CLOCK_REALTIME);
+  clk->clock_type = GPR_CLOCK_PRECISE;
 }
 #endif /* GRPC_TIMERS_RDTSC */
 
-#endif /* GRPC_CORE_PROFILING_TIMERS_PRECISECLOCK_H */
+#endif /* GRPC_CORE_SUPPORT_TIME_PRECISE_ */
diff --git a/src/core/support/time_win32.c b/src/core/support/time_win32.c
index 7f64c80..f794855 100644
--- a/src/core/support/time_win32.c
+++ b/src/core/support/time_win32.c
@@ -38,6 +38,7 @@
 #ifdef GPR_WIN32
 
 #include <grpc/support/time.h>
+#include <src/core/support/time_precise.h>
 #include <sys/timeb.h>
 
 static LARGE_INTEGER g_start_time;
@@ -68,6 +69,9 @@
       now_tv.tv_sec = (time_t)now_dbl;
       now_tv.tv_nsec = (int)((now_dbl - (double)now_tv.tv_sec) * 1e9);
       break;
+    case GPR_CLOCK_PRECISE:
+      gpr_precise_clock_now(&now_tv);
+      break;
   }
   return now_tv;
 }
diff --git a/src/core/surface/call.c b/src/core/surface/call.c
index 33f277d..4426bbb 100644
--- a/src/core/surface/call.c
+++ b/src/core/surface/call.c
@@ -1046,10 +1046,11 @@
                                                (const gpr_uint8 *)md->value,
                                                md->value_length, 1);
     if (!grpc_mdstr_is_legal_header(l->md->key)) {
-      gpr_log(GPR_ERROR, "attempt to send invalid metadata 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_mdstr_is_bin_suffixed(l->md->key) &&
-               !grpc_mdstr_is_legal_header(l->md->value)) {
+               !grpc_mdstr_is_legal_nonbin_header(l->md->value)) {
       gpr_log(GPR_ERROR, "attempt to send invalid metadata value");
       return 0;
     }
diff --git a/src/core/surface/channel.c b/src/core/surface/channel.c
index e502515..586402e 100644
--- a/src/core/surface/channel.c
+++ b/src/core/surface/channel.c
@@ -40,6 +40,7 @@
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.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/call.h"
@@ -70,6 +71,7 @@
   grpc_mdstr *grpc_message_string;
   grpc_mdstr *path_string;
   grpc_mdstr *authority_string;
+  grpc_mdelem *default_authority;
   /** mdelem for grpc-status: 0 thru grpc-status: 2 */
   grpc_mdelem *grpc_status_elem[NUM_CACHED_STATUS_ELEMS];
 
@@ -134,10 +136,47 @@
         } else {
           channel->max_message_length = 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: must be an 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(
+              mdctx, ":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: must be an 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: default host already set some other way",
+                    GRPC_ARG_DEFAULT_AUTHORITY);
+          } else {
+            channel->default_authority = grpc_mdelem_from_strings(
+                mdctx, ":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(
+          channel->metadata_context, ":authority", default_authority);
+    }
+    gpr_free(default_authority);
+  }
+
   grpc_channel_stack_init(filters, num_filters, channel, args,
                           channel->metadata_context,
                           CHANNEL_STACK_FROM_CHANNEL(channel));
@@ -161,6 +200,8 @@
   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,
@@ -251,6 +292,9 @@
     }
     gpr_free(rc);
   }
+  if (channel->default_authority != NULL) {
+    GRPC_MDELEM_UNREF(channel->default_authority);
+  }
   grpc_mdctx_unref(channel->metadata_context);
   gpr_mu_destroy(&channel->registered_call_mu);
   gpr_free(channel->target);
diff --git a/src/core/surface/init.c b/src/core/surface/init.c
index d904454..0d48cd4 100644
--- a/src/core/surface/init.c
+++ b/src/core/surface/init.c
@@ -86,11 +86,11 @@
   if (++g_initializations == 1) {
     gpr_time_init();
     grpc_resolver_registry_init("dns:///");
-    grpc_register_resolver_type("dns", grpc_dns_resolver_factory_create());
-    grpc_register_resolver_type("ipv4", grpc_ipv4_resolver_factory_create());
-    grpc_register_resolver_type("ipv6", grpc_ipv6_resolver_factory_create());
+    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("unix", grpc_unix_resolver_factory_create());
+    grpc_register_resolver_type(grpc_unix_resolver_factory_create());
 #endif
     grpc_register_tracer("channel", &grpc_trace_channel);
     grpc_register_tracer("surface", &grpc_surface_trace);
diff --git a/src/core/transport/metadata.c b/src/core/transport/metadata.c
index f92e87e..3fd21a2 100644
--- a/src/core/transport/metadata.c
+++ b/src/core/transport/metadata.c
@@ -681,16 +681,34 @@
 
 void grpc_mdctx_unlock(grpc_mdctx *ctx) { unlock(ctx); }
 
-int grpc_mdstr_is_legal_header(grpc_mdstr *s) {
-  /* TODO(ctiller): consider caching this, or computing it on construction */
+static int conforms_to(grpc_mdstr *s, const gpr_uint8 *legal_bits) {
   const gpr_uint8 *p = GPR_SLICE_START_PTR(s->slice);
   const gpr_uint8 *e = GPR_SLICE_END_PTR(s->slice);
   for (; p != e; p++) {
-    if (*p < 32 || *p > 126) return 0;
+    int idx = *p;
+    int byte = idx / 8;
+    int bit = idx % 8;
+    if ((legal_bits[byte] & (1 << bit)) == 0) return 0;
   }
   return 1;
 }
 
+int grpc_mdstr_is_legal_header(grpc_mdstr *s) {
+  static const gpr_uint8 legal_header_bits[256 / 8] = {
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 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};
+  return conforms_to(s, legal_header_bits);
+}
+
+int grpc_mdstr_is_legal_nonbin_header(grpc_mdstr *s) {
+  static const gpr_uint8 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(s, legal_header_bits);
+}
+
 int grpc_mdstr_is_bin_suffixed(grpc_mdstr *s) {
   /* TODO(ctiller): consider caching this */
   return grpc_is_binary_header((const char *)GPR_SLICE_START_PTR(s->slice),
diff --git a/src/core/transport/metadata.h b/src/core/transport/metadata.h
index a7af49b..eb17747 100644
--- a/src/core/transport/metadata.h
+++ b/src/core/transport/metadata.h
@@ -154,6 +154,7 @@
 const char *grpc_mdstr_as_c_string(grpc_mdstr *s);
 
 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);
 
 /* Batch mode metadata functions.
diff --git a/src/python/grpcio_test/grpc_test/_adapter/_links_test.py b/src/python/grpcio_test/grpc_test/_adapter/_links_test.py
index c4686b3..4077b8e 100644
--- a/src/python/grpcio_test/grpc_test/_adapter/_links_test.py
+++ b/src/python/grpcio_test/grpc_test/_adapter/_links_test.py
@@ -46,8 +46,8 @@
 # TODO(nathaniel): End-to-end metadata testing.
 def _transform_metadata(unused_metadata):
   return (
-      ('one unused key', 'one unused value'),
-      ('another unused key', 'another unused value'),
+      ('one_unused_key', 'one unused value'),
+      ('another_unused_key', 'another unused value'),
 )
 
 
diff --git a/src/python/grpcio_test/grpc_test/_cython/adapter_low_test.py b/src/python/grpcio_test/grpc_test/_cython/adapter_low_test.py
index 9bab930..f1bec23 100644
--- a/src/python/grpcio_test/grpc_test/_cython/adapter_low_test.py
+++ b/src/python/grpcio_test/grpc_test/_cython/adapter_low_test.py
@@ -76,7 +76,7 @@
     CLIENT_METADATA_BIN_VALUE = b'\0'*1000
     SERVER_INITIAL_METADATA_KEY = 'init_me_me_me'
     SERVER_INITIAL_METADATA_VALUE = 'whodawha?'
-    SERVER_TRAILING_METADATA_KEY = 'California_is_in_a_drought'
+    SERVER_TRAILING_METADATA_KEY = 'california_is_in_a_drought'
     SERVER_TRAILING_METADATA_VALUE = 'zomg it is'
     SERVER_STATUS_CODE = _types.StatusCode.OK
     SERVER_STATUS_DETAILS = 'our work is never over'
diff --git a/src/python/grpcio_test/grpc_test/_links/_transmission_test.py b/src/python/grpcio_test/grpc_test/_links/_transmission_test.py
index 02ddd51..db011bc 100644
--- a/src/python/grpcio_test/grpc_test/_links/_transmission_test.py
+++ b/src/python/grpcio_test/grpc_test/_links/_transmission_test.py
@@ -66,9 +66,9 @@
 
   def create_invocation_initial_metadata(self):
     return (
-        ('first invocation initial metadata key', 'just a string value'),
-        ('second invocation initial metadata key', '0123456789'),
-        ('third invocation initial metadata key-bin', '\x00\x57' * 100),
+        ('first_invocation_initial_metadata_key', 'just a string value'),
+        ('second_invocation_initial_metadata_key', '0123456789'),
+        ('third_invocation_initial_metadata_key-bin', '\x00\x57' * 100),
     )
 
   def create_invocation_terminal_metadata(self):
@@ -76,16 +76,16 @@
 
   def create_service_initial_metadata(self):
     return (
-        ('first service initial metadata key', 'just another string value'),
-        ('second service initial metadata key', '9876543210'),
-        ('third service initial metadata key-bin', '\x00\x59\x02' * 100),
+        ('first_service_initial_metadata_key', 'just another string value'),
+        ('second_service_initial_metadata_key', '9876543210'),
+        ('third_service_initial_metadata_key-bin', '\x00\x59\x02' * 100),
     )
 
   def create_service_terminal_metadata(self):
     return (
-        ('first service terminal metadata key', 'yet another string value'),
-        ('second service terminal metadata key', 'abcdefghij'),
-        ('third service terminal metadata key-bin', '\x00\x37' * 100),
+        ('first_service_terminal_metadata_key', 'yet another string value'),
+        ('second_service_terminal_metadata_key', 'abcdefghij'),
+        ('third_service_terminal_metadata_key-bin', '\x00\x37' * 100),
     )
 
   def create_invocation_completion(self):
diff --git a/src/python/grpcio_test/setup.py b/src/python/grpcio_test/setup.py
index a6203ca..898ea20 100644
--- a/src/python/grpcio_test/setup.py
+++ b/src/python/grpcio_test/setup.py
@@ -61,6 +61,7 @@
     'pytest>=2.6',
     'pytest-cov>=2.0',
     'pytest-xdist>=1.11',
+    'pytest-timeout>=0.5',
 )
 
 _INSTALL_REQUIRES = (
diff --git a/templates/Makefile.template b/templates/Makefile.template
index 00582a2..797f0ab 100644
--- a/templates/Makefile.template
+++ b/templates/Makefile.template
@@ -859,8 +859,8 @@
 	$(Q)(cd third_party/openssl ; CC="$(CC) $(PIC_CPPFLAGS) -fvisibility=hidden $(CPPFLAGS_$(CONFIG)) $(OPENSSL_CFLAGS_$(CONFIG)) $(OPENSSL_CFLAGS_EXTRA)" ./config no-asm $(OPENSSL_CONFIG_$(CONFIG)))
 endif
 endif
-	$(Q)$(MAKE) -C third_party/openssl clean
-	$(Q)(unset CPPFLAGS; $(MAKE) -C third_party/openssl build_crypto build_ssl)
+	$(Q)$(MAKE) -j 1 -C third_party/openssl clean
+	$(Q)(unset CPPFLAGS; $(MAKE) -j 1 -C third_party/openssl build_crypto build_ssl)
 	$(Q)mkdir -p $(LIBDIR)/$(CONFIG)/openssl
 	$(Q)cp third_party/openssl/libssl.a third_party/openssl/libcrypto.a $(LIBDIR)/$(CONFIG)/openssl
 
diff --git a/test/core/end2end/tests/default_host.c b/test/core/end2end/tests/default_host.c
index 97c19db..57f65b8 100644
--- a/test/core/end2end/tests/default_host.c
+++ b/test/core/end2end/tests/default_host.c
@@ -201,7 +201,7 @@
   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, "localhost"));
+  GPR_ASSERT(0 == strncmp(call_details.host, "localhost", 9));
   GPR_ASSERT(was_cancelled == 1);
 
   gpr_free(details);
diff --git a/test/cpp/end2end/generic_end2end_test.cc b/test/cpp/end2end/generic_end2end_test.cc
index de7eab8..809eef0 100644
--- a/test/cpp/end2end/generic_end2end_test.cc
+++ b/test/cpp/end2end/generic_end2end_test.cc
@@ -160,7 +160,7 @@
                                    srv_cq_.get(), tag(4));
 
       verify_ok(srv_cq_.get(), 4, true);
-      EXPECT_EQ(server_host_, srv_ctx.host());
+      EXPECT_EQ(server_host_, srv_ctx.host().substr(0, server_host_.length()));
       EXPECT_EQ(kMethodName, srv_ctx.method());
       ByteBuffer recv_buffer;
       stream.Read(&recv_buffer, tag(5));
@@ -233,7 +233,7 @@
                                srv_cq_.get(), tag(2));
 
   verify_ok(srv_cq_.get(), 2, true);
-  EXPECT_EQ(server_host_, srv_ctx.host());
+  EXPECT_EQ(server_host_, srv_ctx.host().substr(0, server_host_.length()));
   EXPECT_EQ(kMethodName, srv_ctx.method());
 
   std::unique_ptr<ByteBuffer> send_buffer =
diff --git a/test/cpp/interop/interop_client.cc b/test/cpp/interop/interop_client.cc
index fa35858..ca13cdc 100644
--- a/test/cpp/interop/interop_client.cc
+++ b/test/cpp/interop/interop_client.cc
@@ -362,20 +362,37 @@
       request.set_response_type(payload_types[i]);
       request.set_response_compression(compression_types[j]);
 
-      for (unsigned int i = 0; i < response_stream_sizes.size(); ++i) {
+      for (size_t k = 0; k < response_stream_sizes.size(); ++k) {
         ResponseParameters* response_parameter =
             request.add_response_parameters();
-        response_parameter->set_size(response_stream_sizes[i]);
+        response_parameter->set_size(response_stream_sizes[k]);
       }
       StreamingOutputCallResponse response;
 
       std::unique_ptr<ClientReader<StreamingOutputCallResponse>> stream(
           stub->StreamingOutputCall(&context, request));
 
-      unsigned int i = 0;
+      size_t k = 0;
       while (stream->Read(&response)) {
-        GPR_ASSERT(response.payload().body() ==
-                   grpc::string(response_stream_sizes[i], '\0'));
+        // Payload related checks.
+        if (request.response_type() != PayloadType::RANDOM) {
+          GPR_ASSERT(response.payload().type() == request.response_type());
+        }
+        switch (response.payload().type()) {
+          case PayloadType::COMPRESSABLE:
+            GPR_ASSERT(response.payload().body() ==
+                       grpc::string(response_stream_sizes[k], '\0'));
+            break;
+          case PayloadType::UNCOMPRESSABLE: {
+            std::ifstream rnd_file(kRandomFile);
+            GPR_ASSERT(rnd_file.good());
+            for (int n = 0; n < response_stream_sizes[k]; n++) {
+              GPR_ASSERT(response.payload().body()[n] == (char)rnd_file.get());
+            }
+          } break;
+          default:
+            GPR_ASSERT(false);
+        }
 
         // Compression related checks.
         GPR_ASSERT(request.response_compression() ==
@@ -391,10 +408,10 @@
                      GRPC_WRITE_INTERNAL_COMPRESS);
         }
 
-        ++i;
+        ++k;
       }
 
-      GPR_ASSERT(response_stream_sizes.size() == i);
+      GPR_ASSERT(response_stream_sizes.size() == k);
       Status s = stream->Finish();
 
       AssertOkOrPrintErrorStatus(s);
diff --git a/test/cpp/interop/server.cc b/test/cpp/interop/server.cc
index 35ec890..4921fde 100644
--- a/test/cpp/interop/server.cc
+++ b/test/cpp/interop/server.cc
@@ -158,11 +158,13 @@
     SetResponseCompression(context, *request);
     StreamingOutputCallResponse response;
     bool write_success = true;
-    response.mutable_payload()->set_type(request->response_type());
     for (int i = 0; write_success && i < request->response_parameters_size();
          i++) {
-      response.mutable_payload()->set_body(
-          grpc::string(request->response_parameters(i).size(), '\0'));
+      if (!SetPayload(request->response_type(),
+                      request->response_parameters(i).size(),
+                      response.mutable_payload())) {
+        return Status(grpc::StatusCode::INTERNAL, "Error creating payload.");
+      }
       write_success = writer->Write(response);
     }
     if (write_success) {
diff --git a/tools/codegen/core/gen_legal_metadata_characters.c b/tools/codegen/core/gen_legal_metadata_characters.c
new file mode 100644
index 0000000..5c290f2
--- /dev/null
+++ b/tools/codegen/core/gen_legal_metadata_characters.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.
+ *
+ */
+
+/* generates constant table for metadata.c */
+
+#include <stdio.h>
+#include <string.h>
+
+static unsigned char legal_bits[256 / 8];
+
+static void legal(int x) {
+  int byte = x / 8;
+  int bit = x % 8;
+  legal_bits[byte] |= 1 << bit;
+}
+
+static void dump(void) {
+  int i;
+
+  printf("static const gpr_uint8 legal_header_bits[256/8] = ");
+  for (i = 0; i < 256 / 8; i++)
+    printf("%c 0x%02x", i ? ',' : '{', legal_bits[i]);
+  printf(" };\n");
+}
+
+static void clear(void) { memset(legal_bits, 0, sizeof(legal_bits)); }
+
+int main(void) {
+  int i;
+
+  clear();
+  for (i = 'a'; i <= 'z'; i++) legal(i);
+  for (i = '0'; i <= '9'; i++) legal(i);
+  legal('-');
+  legal('_');
+  dump();
+
+  clear();
+  for (i = 32; i <= 126; i++) legal(i);
+  dump();
+
+  return 0;
+}
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index 06f0f4e..7d5df66 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -845,7 +845,6 @@
 src/core/json/json_reader.h \
 src/core/json/json_writer.h \
 src/core/profiling/timers.h \
-src/core/profiling/timers_preciseclock.h \
 src/core/statistics/census_interface.h \
 src/core/statistics/census_rpc_stats.h \
 src/core/surface/byte_buffer_queue.h \
@@ -1058,6 +1057,7 @@
 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/alloc.c \
 src/core/support/cmdline.c \
 src/core/support/cpu_iphone.c \
diff --git a/tools/run_tests/jobset.py b/tools/run_tests/jobset.py
index 2a86319..79dde55 100755
--- a/tools/run_tests/jobset.py
+++ b/tools/run_tests/jobset.py
@@ -174,6 +174,7 @@
     for k, v in add_env.iteritems():
       env[k] = v
     self._start = time.time()
+    print spec.cmdline
     self._process = subprocess.Popen(args=spec.cmdline,
                                      stderr=subprocess.STDOUT,
                                      stdout=self._tempfile,
diff --git a/tools/run_tests/run_csharp.bat b/tools/run_tests/run_csharp.bat
index c861367..310cfe0 100644
--- a/tools/run_tests/run_csharp.bat
+++ b/tools/run_tests/run_csharp.bat
@@ -8,7 +8,7 @@
 @rem set UUID variable to a random GUID, we will use it to put TestResults.xml to a dedicated directory, so that parallel test runs don't collide
 for /F %%i in ('powershell -Command "[guid]::NewGuid().ToString()"') do (set UUID=%%i)
 
-packages\NUnit.Runners.2.6.4\tools\nunit-console-x86.exe -labels "%1/bin/Debug/%1.dll" -work test-results/%UUID% || goto :error
+packages\NUnit.Runners.2.6.4\tools\nunit-console-x86.exe /domain:None -labels "%1/bin/Debug/%1.dll" -work test-results/%UUID% || goto :error
 
 endlocal
 
diff --git a/tools/run_tests/run_python.sh b/tools/run_tests/run_python.sh
index 6fdca93..858f300 100755
--- a/tools/run_tests/run_python.sh
+++ b/tools/run_tests/run_python.sh
@@ -47,4 +47,4 @@
 "python"$PYVER -m grpc_test._core_over_links_base_interface_test
 "python"$PYVER -m grpc_test.framework.core._base_interface_test
 
-"python"$PYVER $GRPCIO_TEST/setup.py test -a "-n8 --cov=grpc --junitxml=./report.xml"
+"python"$PYVER $GRPCIO_TEST/setup.py test -a "-n8 --cov=grpc --junitxml=./report.xml --timeout=300"
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index beb4343..8085400 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -465,7 +465,8 @@
 if platform.system() == 'Windows':
   def make_jobspec(cfg, targets):
     return jobset.JobSpec(['make.bat', 'CONFIG=%s' % cfg] + targets,
-                          cwd='vsprojects', shell=True)
+                          cwd='vsprojects', shell=True, 
+                          timeout_seconds=30*60)
 else:
   def make_jobspec(cfg, targets):
     return jobset.JobSpec([os.getenv('MAKE', 'make'),
@@ -535,7 +536,8 @@
   # if not running ==> start a new one
   # otherwise, leave it up
   try:
-    version = urllib2.urlopen('http://localhost:%d/version' % port_server_port).read()
+    version = urllib2.urlopen('http://localhost:%d/version' % port_server_port,
+                              timeout=1).read()
     running = True
   except Exception:
     running = False
@@ -553,12 +555,20 @@
         stderr=subprocess.STDOUT,
         stdout=port_log)
     # ensure port server is up
+    waits = 0
     while True:
+      if waits > 10:
+        port_server.kill()
+        print "port_server failed to start"
+        sys.exit(1)
       try:
-        urllib2.urlopen('http://localhost:%d/get' % port_server_port).read()
+        urllib2.urlopen('http://localhost:%d/get' % port_server_port,
+                        timeout=1).read()
         break
       except urllib2.URLError:
+        print "waiting for port_server"
         time.sleep(0.5)
+        waits += 1
       except:
         port_server.kill()
         raise
diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json
index a89e534..d266c96 100644
--- a/tools/run_tests/sources_and_headers.json
+++ b/tools/run_tests/sources_and_headers.json
@@ -238,6 +238,15 @@
     ]
   }, 
   {
+    "deps": [], 
+    "headers": [], 
+    "language": "c", 
+    "name": "gen_legal_metadata_characters", 
+    "src": [
+      "tools/codegen/core/gen_legal_metadata_characters.c"
+    ]
+  }, 
+  {
     "deps": [
       "gpr", 
       "gpr_test_util"
@@ -12159,7 +12168,8 @@
       "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/thd_internal.h", 
+      "src/core/support/time_precise.h"
     ], 
     "language": "c", 
     "name": "gpr", 
@@ -12233,6 +12243,7 @@
       "src/core/support/thd_win32.c", 
       "src/core/support/time.c", 
       "src/core/support/time_posix.c", 
+      "src/core/support/time_precise.h", 
       "src/core/support/time_win32.c", 
       "src/core/support/tls_pthread.c"
     ]
@@ -12330,7 +12341,6 @@
       "src/core/json/json_reader.h", 
       "src/core/json/json_writer.h", 
       "src/core/profiling/timers.h", 
-      "src/core/profiling/timers_preciseclock.h", 
       "src/core/security/auth_filters.h", 
       "src/core/security/base64.h", 
       "src/core/security/credentials.h", 
@@ -12533,7 +12543,6 @@
       "src/core/profiling/basic_timers.c", 
       "src/core/profiling/stap_timers.c", 
       "src/core/profiling/timers.h", 
-      "src/core/profiling/timers_preciseclock.h", 
       "src/core/security/auth_filters.h", 
       "src/core/security/base64.c", 
       "src/core/security/base64.h", 
@@ -12809,7 +12818,6 @@
       "src/core/json/json_reader.h", 
       "src/core/json/json_writer.h", 
       "src/core/profiling/timers.h", 
-      "src/core/profiling/timers_preciseclock.h", 
       "src/core/statistics/census_interface.h", 
       "src/core/statistics/census_rpc_stats.h", 
       "src/core/surface/byte_buffer_queue.h", 
@@ -12997,7 +13005,6 @@
       "src/core/profiling/basic_timers.c", 
       "src/core/profiling/stap_timers.c", 
       "src/core/profiling/timers.h", 
-      "src/core/profiling/timers_preciseclock.h", 
       "src/core/statistics/census_interface.h", 
       "src/core/statistics/census_rpc_stats.h", 
       "src/core/surface/byte_buffer.c", 
diff --git a/vsprojects/Grpc.mak b/vsprojects/Grpc.mak
index 19cb397..f8561ab 100644
--- a/vsprojects/Grpc.mak
+++ b/vsprojects/Grpc.mak
@@ -183,6 +183,14 @@
 	echo Running gen_hpack_tables
 	$(OUT_DIR)\gen_hpack_tables.exe
 
+gen_legal_metadata_characters.exe: $(OUT_DIR)
+	echo Building gen_legal_metadata_characters
+	$(CC) $(CFLAGS) /Fo:$(OUT_DIR)\ $(REPO_ROOT)\tools\codegen\core\gen_legal_metadata_characters.c 
+	$(LINK) $(LFLAGS) /OUT:"$(OUT_DIR)\gen_legal_metadata_characters.exe" $(LIBS) $(OUT_DIR)\gen_legal_metadata_characters.obj 
+gen_legal_metadata_characters: gen_legal_metadata_characters.exe
+	echo Running gen_legal_metadata_characters
+	$(OUT_DIR)\gen_legal_metadata_characters.exe
+
 gpr_cmdline_test.exe: build_gpr_test_util build_gpr $(OUT_DIR)
 	echo Building gpr_cmdline_test
 	$(CC) $(CFLAGS) /Fo:$(OUT_DIR)\ $(REPO_ROOT)\test\core\support\cmdline_test.c 
diff --git a/vsprojects/gpr/gpr.vcxproj b/vsprojects/gpr/gpr.vcxproj
index 83c2956..3f8f554 100644
--- a/vsprojects/gpr/gpr.vcxproj
+++ b/vsprojects/gpr/gpr.vcxproj
@@ -158,6 +158,7 @@
     <ClInclude Include="..\..\src\core\support\string.h" />
     <ClInclude Include="..\..\src\core\support\string_win32.h" />
     <ClInclude Include="..\..\src\core\support\thd_internal.h" />
+    <ClInclude Include="..\..\src\core\support\time_precise.h" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="..\..\src\core\support\alloc.c">
diff --git a/vsprojects/gpr/gpr.vcxproj.filters b/vsprojects/gpr/gpr.vcxproj.filters
index 64b9092..b6ac061 100644
--- a/vsprojects/gpr/gpr.vcxproj.filters
+++ b/vsprojects/gpr/gpr.vcxproj.filters
@@ -218,6 +218,9 @@
     <ClInclude Include="..\..\src\core\support\thd_internal.h">
       <Filter>src\core\support</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\src\core\support\time_precise.h">
+      <Filter>src\core\support</Filter>
+    </ClInclude>
   </ItemGroup>
 
   <ItemGroup>
diff --git a/vsprojects/grpc/grpc.vcxproj b/vsprojects/grpc/grpc.vcxproj
index b17eea9..1fa7e4b 100644
--- a/vsprojects/grpc/grpc.vcxproj
+++ b/vsprojects/grpc/grpc.vcxproj
@@ -307,7 +307,6 @@
     <ClInclude Include="..\..\src\core\json\json_reader.h" />
     <ClInclude Include="..\..\src\core\json\json_writer.h" />
     <ClInclude Include="..\..\src\core\profiling\timers.h" />
-    <ClInclude Include="..\..\src\core\profiling\timers_preciseclock.h" />
     <ClInclude Include="..\..\src\core\statistics\census_interface.h" />
     <ClInclude Include="..\..\src\core\statistics\census_rpc_stats.h" />
     <ClInclude Include="..\..\src\core\surface\byte_buffer_queue.h" />
diff --git a/vsprojects/grpc/grpc.vcxproj.filters b/vsprojects/grpc/grpc.vcxproj.filters
index a955e9e..b22818a 100644
--- a/vsprojects/grpc/grpc.vcxproj.filters
+++ b/vsprojects/grpc/grpc.vcxproj.filters
@@ -680,9 +680,6 @@
     <ClInclude Include="..\..\src\core\profiling\timers.h">
       <Filter>src\core\profiling</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\src\core\profiling\timers_preciseclock.h">
-      <Filter>src\core\profiling</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\src\core\statistics\census_interface.h">
       <Filter>src\core\statistics</Filter>
     </ClInclude>
diff --git a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj
index a692c48..3883a32 100644
--- a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj
+++ b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj
@@ -290,7 +290,6 @@
     <ClInclude Include="..\..\src\core\json\json_reader.h" />
     <ClInclude Include="..\..\src\core\json\json_writer.h" />
     <ClInclude Include="..\..\src\core\profiling\timers.h" />
-    <ClInclude Include="..\..\src\core\profiling\timers_preciseclock.h" />
     <ClInclude Include="..\..\src\core\statistics\census_interface.h" />
     <ClInclude Include="..\..\src\core\statistics\census_rpc_stats.h" />
     <ClInclude Include="..\..\src\core\surface\byte_buffer_queue.h" />
diff --git a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters
index 1c4036d..d12abc0 100644
--- a/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters
+++ b/vsprojects/grpc_unsecure/grpc_unsecure.vcxproj.filters
@@ -578,9 +578,6 @@
     <ClInclude Include="..\..\src\core\profiling\timers.h">
       <Filter>src\core\profiling</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\src\core\profiling\timers_preciseclock.h">
-      <Filter>src\core\profiling</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\src\core\statistics\census_interface.h">
       <Filter>src\core\statistics</Filter>
     </ClInclude>