Merge github.com:grpc/grpc into yeah-we-know-what-youre-talking-about

Conflicts:
	src/core/channel/http_client_filter.c
	src/core/surface/channel.c
diff --git a/build.json b/build.json
index 943c5f2..850b404 100644
--- a/build.json
+++ b/build.json
@@ -1895,6 +1895,9 @@
         "grpc",
         "gpr_test_util",
         "gpr"
+      ],
+      "platforms": [
+        "posix"
       ]
     },
     {
@@ -1912,6 +1915,9 @@
         "grpc",
         "gpr_test_util",
         "gpr"
+      ],
+      "platforms": [
+        "posix"
       ]
     },
     {
@@ -1970,6 +1976,9 @@
         "grpc",
         "gpr_test_util",
         "gpr"
+      ],
+      "platforms": [
+        "posix"
       ]
     },
     {
@@ -2208,6 +2217,9 @@
         "gpr_test_util",
         "gpr",
         "grpc++_test_config"
+      ],
+      "platforms": [
+        "posix"
       ]
     },
     {
@@ -2226,6 +2238,9 @@
         "gpr_test_util",
         "gpr",
         "grpc++_test_config"
+      ],
+      "platforms": [
+        "posix"
       ]
     },
     {
@@ -2240,6 +2255,9 @@
         "grpc",
         "gpr_test_util",
         "gpr"
+      ],
+      "platforms": [
+        "posix"
       ]
     },
     {
@@ -2344,6 +2362,9 @@
         "grpc",
         "gpr_test_util",
         "gpr"
+      ],
+      "platforms": [
+        "posix"
       ]
     },
     {
@@ -2362,6 +2383,9 @@
         "gpr_test_util",
         "gpr",
         "grpc++_test_config"
+      ],
+      "platforms": [
+        "posix"
       ]
     },
     {
@@ -2380,6 +2404,9 @@
         "gpr_test_util",
         "gpr",
         "grpc++_test_config"
+      ],
+      "platforms": [
+        "posix"
       ]
     },
     {
@@ -2431,6 +2458,9 @@
         "grpc",
         "gpr_test_util",
         "gpr"
+      ],
+      "platforms": [
+        "posix"
       ]
     },
     {
@@ -2480,6 +2510,9 @@
         "grpc",
         "gpr_test_util",
         "gpr"
+      ],
+      "platforms": [
+        "posix"
       ]
     },
     {
@@ -2497,6 +2530,9 @@
         "grpc",
         "gpr_test_util",
         "gpr"
+      ],
+      "platforms": [
+        "posix"
       ]
     },
     {
diff --git a/include/grpc++/dynamic_thread_pool.h b/include/grpc++/dynamic_thread_pool.h
index bc4e2d4..f0cd359 100644
--- a/include/grpc++/dynamic_thread_pool.h
+++ b/include/grpc++/dynamic_thread_pool.h
@@ -41,6 +41,7 @@
 #include <grpc++/thread_pool_interface.h>
 
 #include <list>
+#include <memory>
 #include <queue>
 
 namespace grpc {
diff --git a/include/grpc++/impl/sync_no_cxx11.h b/include/grpc++/impl/sync_no_cxx11.h
index fda6689..5869b04 100644
--- a/include/grpc++/impl/sync_no_cxx11.h
+++ b/include/grpc++/impl/sync_no_cxx11.h
@@ -87,7 +87,7 @@
   ~condition_variable() { gpr_cv_destroy(&cv_); }
   void wait(lock_guard<mutex> &mu) {
     mu.locked = false;
-    gpr_cv_wait(&cv_, &mu.mu_.mu_, gpr_inf_future(GPR_CLOCK_REALTIME);
+    gpr_cv_wait(&cv_, &mu.mu_.mu_, gpr_inf_future(GPR_CLOCK_REALTIME));
     mu.locked = true;
   }
   void notify_one() { gpr_cv_signal(&cv_); }
diff --git a/include/grpc++/server_credentials.h b/include/grpc++/server_credentials.h
index 83ae9fd..11acd67 100644
--- a/include/grpc++/server_credentials.h
+++ b/include/grpc++/server_credentials.h
@@ -58,12 +58,15 @@
 
 // Options to create ServerCredentials with SSL
 struct SslServerCredentialsOptions {
+  SslServerCredentialsOptions() : force_client_auth(false) {}
+
   struct PemKeyCertPair {
     grpc::string private_key;
     grpc::string cert_chain;
   };
   grpc::string pem_root_certs;
   std::vector<PemKeyCertPair> pem_key_cert_pairs;
+  bool force_client_auth;
 };
 
 // Builds SSL ServerCredentials given SSL specific options
diff --git a/include/grpc/census.h b/include/grpc/census.h
index 3797839..7603dfd 100644
--- a/include/grpc/census.h
+++ b/include/grpc/census.h
@@ -44,26 +44,30 @@
 extern "C" {
 #endif
 
-/* Identify census functionality that can be enabled via census_initialize(). */
-enum census_functions {
-  CENSUS_NONE = 0,    /* Do not enable census. */
-  CENSUS_TRACING = 1, /* Enable census tracing. */
-  CENSUS_STATS = 2,   /* Enable Census stats collection. */
-  CENSUS_CPU = 4,     /* Enable Census CPU usage collection. */
-  CENSUS_ALL = CENSUS_TRACING | CENSUS_STATS | CENSUS_CPU
+/* Identify census features that can be enabled via census_initialize(). */
+enum census_features {
+  CENSUS_FEATURE_NONE = 0,    /* Do not enable census. */
+  CENSUS_FEATURE_TRACING = 1, /* Enable census tracing. */
+  CENSUS_FEATURE_STATS = 2,   /* Enable Census stats collection. */
+  CENSUS_FEATURE_CPU = 4,     /* Enable Census CPU usage collection. */
+  CENSUS_FEATURE_ALL =
+      CENSUS_FEATURE_TRACING | CENSUS_FEATURE_STATS | CENSUS_FEATURE_CPU
 };
 
-/* Shutdown and startup census subsystem. The 'functions' argument should be
- * the OR (|) of census_functions values. If census fails to initialize, then
+/** Shutdown and startup census subsystem. The 'features' argument should be
+ * the OR (|) of census_features values. If census fails to initialize, then
  * census_initialize() will return a non-zero value. It is an error to call
  * census_initialize() more than once (without an intervening
  * census_shutdown()). */
-int census_initialize(int functions);
-void census_shutdown();
+int census_initialize(int features);
+void census_shutdown(void);
 
-/* If any census feature has been initialized, this funtion will return a
- * non-zero value. */
-int census_available();
+/** Return the features supported by the current census implementation (not all
+ * features will be available on all platforms). */
+int census_supported(void);
+
+/** Return the census features currently enabled. */
+int census_enabled(void);
 
 /* Internally, Census relies on a context, which should be propagated across
  * RPC's. From the RPC subsystems viewpoint, this is an opaque data structure.
diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h
index 8e3bbbf..c548549 100644
--- a/include/grpc/grpc.h
+++ b/include/grpc/grpc.h
@@ -471,8 +471,8 @@
     clients will want to simply pass NULL. See grpc_channel_args definition for
     more on this. The data in 'args' need only live through the invocation of
     this function. */
-grpc_channel *grpc_channel_create(const char *target,
-                                  const grpc_channel_args *args);
+grpc_channel *grpc_insecure_channel_create(const char *target,
+                                           const grpc_channel_args *args);
 
 /** Create a lame client: this client fails every operation attempted on it. */
 grpc_channel *grpc_lame_client_channel_create(const char *target);
diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h
index 29eddc5..ff84050 100644
--- a/include/grpc/grpc_security.h
+++ b/include/grpc/grpc_security.h
@@ -87,7 +87,7 @@
      directory).
    - pem_key_cert_pair is a pointer on the object containing client's private
      key and certificate chain. This parameter can be NULL if the client does
-     not have such a key/cert pair.  */
+     not have such a key/cert pair. */
 grpc_credentials *grpc_ssl_credentials_create(
     const char *pem_root_certs, grpc_ssl_pem_key_cert_pair *pem_key_cert_pair);
 
@@ -174,10 +174,13 @@
    - pem_key_cert_pairs is an array private key / certificate chains of the
      server. This parameter cannot be NULL.
    - num_key_cert_pairs indicates the number of items in the private_key_files
-     and cert_chain_files parameters. It should be at least 1. */
+     and cert_chain_files parameters. It should be at least 1.
+   - 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_root_certs is
+     NULL. */
 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);
+    size_t num_key_cert_pairs, int force_client_auth);
 
 /* --- Server-side secure ports. --- */
 
diff --git a/src/compiler/python_generator.cc b/src/compiler/python_generator.cc
index 724b69c..2982a89 100644
--- a/src/compiler/python_generator.cc
+++ b/src/compiler/python_generator.cc
@@ -249,7 +249,7 @@
   do {
     message_path.push_back(path_elem_type);
     path_elem_type = path_elem_type->containing_type();
-  } while (path_elem_type != nullptr);
+  } while (path_elem_type); // implicit nullptr comparison; don't be explicit
   grpc::string file_name = type->file()->name();
   static const int proto_suffix_length = strlen(".proto");
   if (!(file_name.size() > static_cast<size_t>(proto_suffix_length) &&
diff --git a/src/core/census/grpc_context.c b/src/core/census/grpc_context.c
index 0ed6346..d4243cb 100644
--- a/src/core/census/grpc_context.c
+++ b/src/core/census/grpc_context.c
@@ -39,7 +39,7 @@
 }
 
 void grpc_census_call_set_context(grpc_call *call, census_context *context) {
-  if (!census_available()) {
+  if (census_enabled() == CENSUS_FEATURE_NONE) {
     return;
   }
   if (context == NULL) {
diff --git a/src/core/census/initialize.c b/src/core/census/initialize.c
index 8016520..8d60f79 100644
--- a/src/core/census/initialize.c
+++ b/src/core/census/initialize.c
@@ -33,20 +33,25 @@
 
 #include <grpc/census.h>
 
-static int census_fns_enabled = CENSUS_NONE;
+static int features_enabled = CENSUS_FEATURE_NONE;
 
-int census_initialize(int functions) {
-  if (census_fns_enabled != CENSUS_NONE) {
+int census_initialize(int features) {
+  if (features_enabled != CENSUS_FEATURE_NONE) {
     return 1;
   }
-  if (functions != CENSUS_NONE) {
+  if (features != CENSUS_FEATURE_NONE) {
     return 1;
   } else {
-    census_fns_enabled = functions;
+    features_enabled = features;
     return 0;
   }
 }
 
-void census_shutdown() { census_fns_enabled = CENSUS_NONE; }
+void census_shutdown(void) { features_enabled = CENSUS_FEATURE_NONE; }
 
-int census_available() { return (census_fns_enabled != CENSUS_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/channel/compress_filter.c b/src/core/channel/compress_filter.c
index 4bf24e7..9fc8589 100644
--- a/src/core/channel/compress_filter.c
+++ b/src/core/channel/compress_filter.c
@@ -284,19 +284,19 @@
       grpc_channel_args_get_compression_algorithm(args);
 
   channeld->mdstr_request_compression_algorithm_key =
-      grpc_mdstr_from_string(mdctx, GRPC_COMPRESS_REQUEST_ALGORITHM_KEY);
+      grpc_mdstr_from_string(mdctx, GRPC_COMPRESS_REQUEST_ALGORITHM_KEY, 0);
 
   channeld->mdstr_outgoing_compression_algorithm_key =
-      grpc_mdstr_from_string(mdctx, "grpc-encoding");
+      grpc_mdstr_from_string(mdctx, "grpc-encoding", 0);
 
   for (algo_idx = 0; algo_idx < GRPC_COMPRESS_ALGORITHMS_COUNT; ++algo_idx) {
-    char *algorith_name;
-    GPR_ASSERT(grpc_compression_algorithm_name(algo_idx, &algorith_name) != 0);
+    char *algorithm_name;
+    GPR_ASSERT(grpc_compression_algorithm_name(algo_idx, &algorithm_name) != 0);
     channeld->mdelem_compression_algorithms[algo_idx] =
         grpc_mdelem_from_metadata_strings(
             mdctx,
             grpc_mdstr_ref(channeld->mdstr_outgoing_compression_algorithm_key),
-            grpc_mdstr_from_string(mdctx, algorith_name));
+            grpc_mdstr_from_string(mdctx, algorithm_name, 0));
   }
 
   GPR_ASSERT(!is_last);
diff --git a/src/core/channel/http_client_filter.c b/src/core/channel/http_client_filter.c
index 59a35d1..82232de 100644
--- a/src/core/channel/http_client_filter.c
+++ b/src/core/channel/http_client_filter.c
@@ -244,7 +244,7 @@
 
   tmp = gpr_strvec_flatten(&v, NULL);
   gpr_strvec_destroy(&v);
-  result = grpc_mdstr_from_string(mdctx, tmp);
+  result = grpc_mdstr_from_string(mdctx, tmp, 0);
   gpr_free(tmp);
 
   return result;
@@ -288,7 +288,7 @@
       grpc_mdelem_from_strings(mdctx, "content-type", "application/grpc");
   channeld->status = grpc_mdelem_from_strings(mdctx, ":status", "200");
   channeld->user_agent = grpc_mdelem_from_metadata_strings(
-      mdctx, grpc_mdstr_from_string(mdctx, "user-agent"),
+      mdctx, grpc_mdstr_from_string(mdctx, "user-agent", 0),
       user_agent_from_args(mdctx, channel_args));
 }
 
diff --git a/src/core/channel/http_server_filter.c b/src/core/channel/http_server_filter.c
index 30b011a..0955ae3 100644
--- a/src/core/channel/http_server_filter.c
+++ b/src/core/channel/http_server_filter.c
@@ -258,9 +258,9 @@
   channeld->http_scheme = grpc_mdelem_from_strings(mdctx, ":scheme", "http");
   channeld->https_scheme = grpc_mdelem_from_strings(mdctx, ":scheme", "https");
   channeld->grpc_scheme = grpc_mdelem_from_strings(mdctx, ":scheme", "grpc");
-  channeld->path_key = grpc_mdstr_from_string(mdctx, ":path");
-  channeld->authority_key = grpc_mdstr_from_string(mdctx, ":authority");
-  channeld->host_key = grpc_mdstr_from_string(mdctx, "host");
+  channeld->path_key = grpc_mdstr_from_string(mdctx, ":path", 0);
+  channeld->authority_key = grpc_mdstr_from_string(mdctx, ":authority", 0);
+  channeld->host_key = grpc_mdstr_from_string(mdctx, "host", 0);
   channeld->content_type =
       grpc_mdelem_from_strings(mdctx, "content-type", "application/grpc");
 
diff --git a/src/core/iomgr/tcp_server_windows.c b/src/core/iomgr/tcp_server_windows.c
index cc68050..bcd2aa8 100644
--- a/src/core/iomgr/tcp_server_windows.c
+++ b/src/core/iomgr/tcp_server_windows.c
@@ -79,6 +79,8 @@
 
   /* active port count: how many ports are actually still listening */
   int active_ports;
+  /* number of iomgr callbacks that have been explicitly scheduled during shutdown */
+  int iomgr_callbacks_pending;
 
   /* all listening ports */
   server_port *ports;
@@ -93,6 +95,7 @@
   gpr_mu_init(&s->mu);
   gpr_cv_init(&s->cv);
   s->active_ports = 0;
+  s->iomgr_callbacks_pending = 0;
   s->cb = NULL;
   s->cb_arg = NULL;
   s->ports = gpr_malloc(sizeof(server_port) * INIT_PORT_CAP);
@@ -112,10 +115,10 @@
   for (i = 0; i < s->nports; i++) {
     server_port *sp = &s->ports[i];
     sp->shutting_down = 1;
-    grpc_winsocket_shutdown(sp->socket);
+    s->iomgr_callbacks_pending += grpc_winsocket_shutdown(sp->socket);
   }
   /* This happens asynchronously. Wait while that happens. */
-  while (s->active_ports) {
+  while (s->active_ports || s->iomgr_callbacks_pending) {
     gpr_cv_wait(&s->cv, &s->mu, gpr_inf_future(GPR_CLOCK_REALTIME));
   }
   gpr_mu_unlock(&s->mu);
@@ -254,8 +257,16 @@
 
   /* 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. Let's do nothing. */
-  if (!from_iocp) return;
+     case. We only need to adjust the pending callback count */
+  if (!from_iocp) {
+    gpr_mu_lock(&sp->server->mu);
+    GPR_ASSERT(sp->server->iomgr_callbacks_pending > 0);
+    if (0 == --sp->server->iomgr_callbacks_pending) {
+      gpr_cv_broadcast(&sp->server->cv);
+    }
+    gpr_mu_unlock(&sp->server->mu);
+    return;
+  }
 
   /* The IOCP notified us of a completed operation. Let's grab the results,
       and act accordingly. */
@@ -264,11 +275,12 @@
                                             &transfered_bytes, FALSE, &flags);
   if (!wsa_success) {
     if (sp->shutting_down) {
-      /* During the shutdown case, we ARE expecting an error. So that's swell,
+      /* During the shutdown case, we ARE expecting an error. So that's well,
          and we can wake up the shutdown thread. */
       sp->shutting_down = 0;
       sp->socket->read_info.outstanding = 0;
       gpr_mu_lock(&sp->server->mu);
+      GPR_ASSERT(sp->server->active_ports > 0);
       if (0 == --sp->server->active_ports) {
         gpr_cv_broadcast(&sp->server->cv);
       }
diff --git a/src/core/iomgr/tcp_windows.c b/src/core/iomgr/tcp_windows.c
index 38ae74a..5e0457a 100644
--- a/src/core/iomgr/tcp_windows.c
+++ b/src/core/iomgr/tcp_windows.c
@@ -368,7 +368,14 @@
   return GRPC_ENDPOINT_WRITE_PENDING;
 }
 
-static void win_add_to_pollset(grpc_endpoint *ep, grpc_pollset *pollset) {
+static void win_add_to_pollset(grpc_endpoint *ep, grpc_pollset *ps) {
+  (void) ps;
+  grpc_tcp *tcp = (grpc_tcp *) ep;
+  grpc_iocp_add_socket(tcp->socket);
+}
+
+static void win_add_to_pollset_set(grpc_endpoint *ep, grpc_pollset_set *pss) {
+  (void) pss;
   grpc_tcp *tcp = (grpc_tcp *) ep;
   grpc_iocp_add_socket(tcp->socket);
 }
@@ -402,8 +409,9 @@
 }
 
 static grpc_endpoint_vtable vtable = {win_notify_on_read, win_write,
-                                      win_add_to_pollset, win_shutdown,
-                                      win_destroy,        win_get_peer};
+                                      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));
diff --git a/src/core/security/client_auth_filter.c b/src/core/security/client_auth_filter.c
index 9a69f53..e86b543 100644
--- a/src/core/security/client_auth_filter.c
+++ b/src/core/security/client_auth_filter.c
@@ -80,7 +80,7 @@
   channel_data *chand = elem->channel_data;
   grpc_transport_stream_op_add_cancellation(
       &calld->op, GRPC_STATUS_UNAUTHENTICATED,
-      grpc_mdstr_from_string(chand->md_ctx, error_msg));
+      grpc_mdstr_from_string(chand->md_ctx, error_msg, 0));
   grpc_call_next_op(elem, &calld->op);
 }
 
@@ -316,10 +316,10 @@
       (grpc_channel_security_connector *)GRPC_SECURITY_CONNECTOR_REF(
           sc, "client_auth_filter");
   chand->md_ctx = metadata_context;
-  chand->authority_string = grpc_mdstr_from_string(chand->md_ctx, ":authority");
-  chand->path_string = grpc_mdstr_from_string(chand->md_ctx, ":path");
-  chand->error_msg_key = grpc_mdstr_from_string(chand->md_ctx, "grpc-message");
-  chand->status_key = grpc_mdstr_from_string(chand->md_ctx, "grpc-status");
+  chand->authority_string = grpc_mdstr_from_string(chand->md_ctx, ":authority", 0);
+  chand->path_string = grpc_mdstr_from_string(chand->md_ctx, ":path", 0);
+  chand->error_msg_key = grpc_mdstr_from_string(chand->md_ctx, "grpc-message", 0);
+  chand->status_key = grpc_mdstr_from_string(chand->md_ctx, "grpc-status", 0);
 }
 
 /* Destructor for channel data */
diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c
index 38612cf..15268ce 100644
--- a/src/core/security/credentials.c
+++ b/src/core/security/credentials.c
@@ -259,8 +259,10 @@
 
 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_server_config *config) {
+    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);
@@ -302,14 +304,14 @@
 
 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) {
+    size_t num_key_cert_pairs, int force_client_auth) {
   grpc_ssl_server_credentials *c =
       gpr_malloc(sizeof(grpc_ssl_server_credentials));
   memset(c, 0, sizeof(grpc_ssl_server_credentials));
   c->base.type = GRPC_CREDENTIALS_TYPE_SSL;
   c->base.vtable = &ssl_server_vtable;
   ssl_build_server_config(pem_root_certs, pem_key_cert_pairs,
-                          num_key_cert_pairs, &c->config);
+                          num_key_cert_pairs, force_client_auth, &c->config);
   return &c->base;
 }
 
diff --git a/src/core/security/security_connector.c b/src/core/security/security_connector.c
index f6e423e..726b4c1 100644
--- a/src/core/security/security_connector.c
+++ b/src/core/security/security_connector.c
@@ -653,9 +653,10 @@
       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, ssl_cipher_suites(),
-      alpn_protocol_strings, alpn_protocol_string_lengths,
-      (uint16_t)num_alpn_protocols, &c->handshaker_factory);
+      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));
diff --git a/src/core/security/security_connector.h b/src/core/security/security_connector.h
index a4c723f..2c9aa1c 100644
--- a/src/core/security/security_connector.h
+++ b/src/core/security/security_connector.h
@@ -201,6 +201,7 @@
   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.
diff --git a/src/core/support/stack_lockfree.c b/src/core/support/stack_lockfree.c
index 2844330..f24e272 100644
--- a/src/core/support/stack_lockfree.c
+++ b/src/core/support/stack_lockfree.c
@@ -72,6 +72,11 @@
 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(int entries) {
@@ -86,6 +91,9 @@
   /* 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
 
   /* Point the head at reserved dummy entry */
   stack->head.contents.index = INVALID_ENTRY_INDEX;
@@ -106,6 +114,19 @@
   /* Also post-increment the aba_ctr */
   newhead.contents.aba_ctr = stack->entries[entry].contents.aba_ctr++;
 
+#ifndef NDEBUG
+  /* Check for double push */
+  {
+    int pushed_index = entry / (8*sizeof(gpr_atm));
+    int pushed_bit = entry % (8*sizeof(gpr_atm));
+    gpr_atm old_val;
+
+    old_val = gpr_atm_no_barrier_fetch_add(&stack->pushed[pushed_index],
+					   (gpr_atm)(1UL << pushed_bit));
+    GPR_ASSERT((old_val & (1UL<<pushed_bit)) == 0);
+  }
+#endif
+
   do {
     /* Atomically get the existing head value for use */
     head.atm = gpr_atm_no_barrier_load(&(stack->head.atm));
@@ -119,6 +140,7 @@
 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) {
@@ -128,5 +150,18 @@
         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)(1UL << pushed_bit));
+    GPR_ASSERT((old_val & (1UL<<pushed_bit)) != 0);
+  }
+#endif
+
   return head.contents.index;
 }
diff --git a/src/core/surface/call.c b/src/core/surface/call.c
index a1da822..12378f0 100644
--- a/src/core/surface/call.c
+++ b/src/core/surface/call.c
@@ -932,7 +932,7 @@
     GPR_ASSERT(sizeof(grpc_linked_mdelem) == sizeof(md->internal_data));
     l->md = grpc_mdelem_from_string_and_buffer(call->metadata_context, md->key,
                                                (const gpr_uint8 *)md->value,
-                                               md->value_length);
+                                               md->value_length, 1);
     if (!grpc_mdstr_is_legal_header(l->md->key)) {
       gpr_log(GPR_ERROR, "attempt to send invalid metadata key");
       return 0;
@@ -1203,7 +1203,7 @@
 static grpc_call_error cancel_with_status(grpc_call *c, grpc_status_code status,
                                           const char *description) {
   grpc_mdstr *details =
-      description ? grpc_mdstr_from_string(c->metadata_context, description)
+      description ? grpc_mdstr_from_string(c->metadata_context, description, 0)
                   : NULL;
 
   GPR_ASSERT(status != GRPC_STATUS_OK);
@@ -1497,7 +1497,7 @@
             op->data.send_status_from_server.status_details != NULL
                 ? grpc_mdstr_from_string(
                       call->metadata_context,
-                      op->data.send_status_from_server.status_details)
+                      op->data.send_status_from_server.status_details, 0)
                 : NULL;
         req = &reqs[out++];
         req->op = GRPC_IOREQ_SEND_CLOSE;
diff --git a/src/core/surface/channel.c b/src/core/surface/channel.c
index a84d330..81f673f 100644
--- a/src/core/surface/channel.c
+++ b/src/core/surface/channel.c
@@ -101,19 +101,19 @@
   /* decremented by grpc_channel_destroy */
   gpr_ref_init(&channel->refs, 1);
   channel->metadata_context = mdctx;
-  channel->grpc_status_string = grpc_mdstr_from_string(mdctx, "grpc-status");
+  channel->grpc_status_string = grpc_mdstr_from_string(mdctx, "grpc-status", 0);
   channel->grpc_compression_algorithm_string =
-      grpc_mdstr_from_string(mdctx, "grpc-encoding");
-  channel->grpc_message_string = grpc_mdstr_from_string(mdctx, "grpc-message");
+      grpc_mdstr_from_string(mdctx, "grpc-encoding", 0);
+  channel->grpc_message_string = grpc_mdstr_from_string(mdctx, "grpc-message", 0);
   for (i = 0; i < NUM_CACHED_STATUS_ELEMS; i++) {
     char buf[GPR_LTOA_MIN_BUFSIZE];
     gpr_ltoa(i, buf);
     channel->grpc_status_elem[i] = grpc_mdelem_from_metadata_strings(
         mdctx, GRPC_MDSTR_REF(channel->grpc_status_string),
-        grpc_mdstr_from_string(mdctx, buf));
+        grpc_mdstr_from_string(mdctx, buf, 0));
   }
-  channel->path_string = grpc_mdstr_from_string(mdctx, ":path");
-  channel->authority_string = grpc_mdstr_from_string(mdctx, ":authority");
+  channel->path_string = grpc_mdstr_from_string(mdctx, ":path", 0);
+  channel->authority_string = grpc_mdstr_from_string(mdctx, ":authority", 0);
   gpr_mu_init(&channel->registered_call_mu);
   channel->registered_calls = NULL;
 
@@ -170,11 +170,11 @@
       channel, cq,
       grpc_mdelem_from_metadata_strings(
           channel->metadata_context, GRPC_MDSTR_REF(channel->path_string),
-          grpc_mdstr_from_string(channel->metadata_context, method)),
+          grpc_mdstr_from_string(channel->metadata_context, method, 0)),
       host ?
       grpc_mdelem_from_metadata_strings(
           channel->metadata_context, GRPC_MDSTR_REF(channel->authority_string),
-          grpc_mdstr_from_string(channel->metadata_context, host)) : NULL,
+          grpc_mdstr_from_string(channel->metadata_context, host, 0)) : NULL,
       deadline);
 }
 
@@ -183,10 +183,10 @@
   registered_call *rc = gpr_malloc(sizeof(registered_call));
   rc->path = grpc_mdelem_from_metadata_strings(
       channel->metadata_context, GRPC_MDSTR_REF(channel->path_string),
-      grpc_mdstr_from_string(channel->metadata_context, method));
+      grpc_mdstr_from_string(channel->metadata_context, method, 0));
   rc->authority = host ? grpc_mdelem_from_metadata_strings(
       channel->metadata_context, GRPC_MDSTR_REF(channel->authority_string),
-      grpc_mdstr_from_string(channel->metadata_context, host)) : NULL;
+      grpc_mdstr_from_string(channel->metadata_context, host, 0)) : NULL;
   gpr_mu_lock(&channel->registered_call_mu);
   rc->next = channel->registered_calls;
   channel->registered_calls = rc;
@@ -288,7 +288,7 @@
     gpr_ltoa(i, tmp);
     return grpc_mdelem_from_metadata_strings(
         channel->metadata_context, GRPC_MDSTR_REF(channel->grpc_status_string),
-        grpc_mdstr_from_string(channel->metadata_context, tmp));
+        grpc_mdstr_from_string(channel->metadata_context, tmp, 0));
   }
 }
 
diff --git a/src/core/surface/channel_create.c b/src/core/surface/channel_create.c
index fdc2185..707d615 100644
--- a/src/core/surface/channel_create.c
+++ b/src/core/surface/channel_create.c
@@ -154,8 +154,8 @@
    Asynchronously: - resolve target
                    - connect to it (trying alternatives as presented)
                    - perform handshakes */
-grpc_channel *grpc_channel_create(const char *target,
-                                  const grpc_channel_args *args) {
+grpc_channel *grpc_insecure_channel_create(const char *target,
+                                           const grpc_channel_args *args) {
   grpc_channel *channel = NULL;
 #define MAX_FILTERS 3
   const grpc_channel_filter *filters[MAX_FILTERS];
diff --git a/src/core/surface/init.c b/src/core/surface/init.c
index a015262..442bc72 100644
--- a/src/core/surface/init.c
+++ b/src/core/surface/init.c
@@ -80,8 +80,11 @@
     grpc_security_pre_init();
     grpc_iomgr_init();
     grpc_tracer_init("GRPC_TRACE");
-    if (census_initialize(CENSUS_NONE)) {
-      gpr_log(GPR_ERROR, "Could not initialize census.");
+    /* Only initialize census if noone else has. */
+    if (census_enabled() == CENSUS_FEATURE_NONE) {
+      if (census_initialize(census_supported())) { /* enable all features. */
+        gpr_log(GPR_ERROR, "Could not initialize census.");
+      }
     }
     grpc_timers_global_init();
   }
diff --git a/src/core/surface/server.c b/src/core/surface/server.c
index 335e66a..57db739 100644
--- a/src/core/surface/server.c
+++ b/src/core/surface/server.c
@@ -690,8 +690,8 @@
   GPR_ASSERT(!is_last);
   chand->server = NULL;
   chand->channel = NULL;
-  chand->path_key = grpc_mdstr_from_string(metadata_context, ":path");
-  chand->authority_key = grpc_mdstr_from_string(metadata_context, ":authority");
+  chand->path_key = grpc_mdstr_from_string(metadata_context, ":path", 0);
+  chand->authority_key = grpc_mdstr_from_string(metadata_context, ":authority", 0);
   chand->next = chand->prev = chand;
   chand->registered_methods = NULL;
   chand->connectivity_state = GRPC_CHANNEL_IDLE;
@@ -913,8 +913,8 @@
     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(mdctx, rm->host) : NULL;
-      method = grpc_mdstr_from_string(mdctx, rm->method);
+      host = rm->host ? grpc_mdstr_from_string(mdctx, rm->host, 0) : NULL;
+      method = grpc_mdstr_from_string(mdctx, rm->method, 0);
       hash = GRPC_MDSTR_KV_HASH(host ? host->hash : 0, method->hash);
       for (probes = 0; chand->registered_methods[(hash + probes) % slots]
                            .server_registered_method != NULL;
diff --git a/src/core/transport/chttp2/stream_encoder.c b/src/core/transport/chttp2/stream_encoder.c
index 65b31a5..0f04169 100644
--- a/src/core/transport/chttp2/stream_encoder.c
+++ b/src/core/transport/chttp2/stream_encoder.c
@@ -441,7 +441,7 @@
       gpr_time_sub(deadline, gpr_now(deadline.clock_type)), timeout_str);
   mdelem = grpc_mdelem_from_metadata_strings(
       c->mdctx, GRPC_MDSTR_REF(c->timeout_key_str),
-      grpc_mdstr_from_string(c->mdctx, timeout_str));
+      grpc_mdstr_from_string(c->mdctx, timeout_str, 0));
   mdelem = hpack_enc(c, mdelem, st);
   if (mdelem) GRPC_MDELEM_UNREF(mdelem);
 }
@@ -456,7 +456,7 @@
                                        grpc_mdctx *ctx) {
   memset(c, 0, sizeof(*c));
   c->mdctx = ctx;
-  c->timeout_key_str = grpc_mdstr_from_string(ctx, "grpc-timeout");
+  c->timeout_key_str = grpc_mdstr_from_string(ctx, "grpc-timeout", 0);
 }
 
 void grpc_chttp2_hpack_compressor_destroy(grpc_chttp2_hpack_compressor *c) {
diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c
index ca10070..1ea4a82 100644
--- a/src/core/transport/chttp2_transport.c
+++ b/src/core/transport/chttp2_transport.c
@@ -232,7 +232,7 @@
   t->global.pings.next = t->global.pings.prev = &t->global.pings;
   t->parsing.is_client = is_client;
   t->parsing.str_grpc_timeout =
-      grpc_mdstr_from_string(t->metadata_context, "grpc-timeout");
+      grpc_mdstr_from_string(t->metadata_context, "grpc-timeout", 0);
   t->parsing.deframe_state =
       is_client ? GRPC_DTS_FH_0 : GRPC_DTS_CLIENT_PREFIX_0;
   t->writing.is_client = is_client;
diff --git a/src/core/transport/metadata.c b/src/core/transport/metadata.c
index e95b7a2..967fd48 100644
--- a/src/core/transport/metadata.c
+++ b/src/core/transport/metadata.c
@@ -309,7 +309,37 @@
   unlock(ctx);
 }
 
-grpc_mdstr *grpc_mdstr_from_string(grpc_mdctx *ctx, const char *str) {
+grpc_mdstr *grpc_mdstr_from_string(grpc_mdctx *ctx, const char *str, int canonicalize_key) {
+  if (canonicalize_key) {
+    size_t len;
+    size_t i;
+    int canonical = 1;
+
+    for (i = 0; str[i]; i++) {
+      if (str[i] >= 'A' && str[i] <= 'Z') {
+        canonical = 0;
+        /* Keep going in loop just to get string length */
+      }
+    }
+    len = i;
+
+    if (canonical) {
+      return grpc_mdstr_from_buffer(ctx, (const gpr_uint8 *)str, len);
+    } else {
+      char *copy = gpr_malloc(len);
+      grpc_mdstr *ret;
+      for (i = 0; i < len; i++) {
+        if (str[i] >= 'A' && str[i] <= 'Z') {
+          copy[i] = str[i] - 'A' + 'a';
+        } else {
+          copy[i] = str[i];
+        }
+      }
+      ret = grpc_mdstr_from_buffer(ctx, (const gpr_uint8 *)copy, len);
+      gpr_free(copy);
+      return ret;
+    }
+  }
   return grpc_mdstr_from_buffer(ctx, (const gpr_uint8 *)str, strlen(str));
 }
 
@@ -491,8 +521,8 @@
 grpc_mdelem *grpc_mdelem_from_strings(grpc_mdctx *ctx, const char *key,
                                       const char *value) {
   return grpc_mdelem_from_metadata_strings(ctx,
-                                           grpc_mdstr_from_string(ctx, key),
-                                           grpc_mdstr_from_string(ctx, value));
+                                           grpc_mdstr_from_string(ctx, key, 0),
+                                           grpc_mdstr_from_string(ctx, value, 0));
 }
 
 grpc_mdelem *grpc_mdelem_from_slices(grpc_mdctx *ctx, gpr_slice key,
@@ -504,9 +534,10 @@
 grpc_mdelem *grpc_mdelem_from_string_and_buffer(grpc_mdctx *ctx,
                                                 const char *key,
                                                 const gpr_uint8 *value,
-                                                size_t value_length) {
+                                                size_t value_length,
+                                                int canonicalize_key) {
   return grpc_mdelem_from_metadata_strings(
-      ctx, grpc_mdstr_from_string(ctx, key),
+      ctx, grpc_mdstr_from_string(ctx, key, canonicalize_key),
       grpc_mdstr_from_buffer(ctx, value, value_length));
 }
 
diff --git a/src/core/transport/metadata.h b/src/core/transport/metadata.h
index 99b1532..15ef9bb 100644
--- a/src/core/transport/metadata.h
+++ b/src/core/transport/metadata.h
@@ -95,7 +95,7 @@
 
 /* Constructors for grpc_mdstr instances; take a variety of data types that
    clients may have handy */
-grpc_mdstr *grpc_mdstr_from_string(grpc_mdctx *ctx, const char *str);
+grpc_mdstr *grpc_mdstr_from_string(grpc_mdctx *ctx, const char *str, int perform_key_canonicalization);
 /* Unrefs the slice. */
 grpc_mdstr *grpc_mdstr_from_slice(grpc_mdctx *ctx, gpr_slice slice);
 grpc_mdstr *grpc_mdstr_from_buffer(grpc_mdctx *ctx, const gpr_uint8 *str,
@@ -117,7 +117,8 @@
 grpc_mdelem *grpc_mdelem_from_string_and_buffer(grpc_mdctx *ctx,
                                                 const char *key,
                                                 const gpr_uint8 *value,
-                                                size_t value_length);
+                                                size_t value_length,
+                                                int canonicalize_key);
 
 /* Mutator and accessor for grpc_mdelem user data. The destructor function
    is used as a type tag and is checked during user_data fetch. */
diff --git a/src/core/tsi/ssl_transport_security.c b/src/core/tsi/ssl_transport_security.c
index 6156a39..609fc06 100644
--- a/src/core/tsi/ssl_transport_security.c
+++ b/src/core/tsi/ssl_transport_security.c
@@ -1293,8 +1293,8 @@
     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, const char* cipher_list,
-    const unsigned char** alpn_protocols,
+    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;
@@ -1349,6 +1349,7 @@
       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,
@@ -1358,7 +1359,8 @@
           break;
         }
         SSL_CTX_set_client_CA_list(impl->ssl_contexts[i], root_names);
-        SSL_CTX_set_verify(impl->ssl_contexts[i], SSL_VERIFY_PEER, NULL);
+        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. */
       }
 
diff --git a/src/core/tsi/ssl_transport_security.h b/src/core/tsi/ssl_transport_security.h
index b2aa2f3..4bf6c81 100644
--- a/src/core/tsi/ssl_transport_security.h
+++ b/src/core/tsi/ssl_transport_security.h
@@ -107,10 +107,14 @@
    - 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 ask the client to authenticate itself with a certificate (server-
-     only authentication mode).
-   - pem_client_roots_size is the size of the associated buffer.
+     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.
@@ -131,8 +135,8 @@
     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, const char* cipher_suites,
-    const unsigned char** alpn_protocols,
+    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);
 
diff --git a/src/cpp/client/insecure_credentials.cc b/src/cpp/client/insecure_credentials.cc
index 5ad8784..e802fa8 100644
--- a/src/cpp/client/insecure_credentials.cc
+++ b/src/cpp/client/insecure_credentials.cc
@@ -49,7 +49,7 @@
     grpc_channel_args channel_args;
     args.SetChannelArgs(&channel_args);
     return std::shared_ptr<ChannelInterface>(new Channel(
-        target, grpc_channel_create(target.c_str(), &channel_args)));
+        target, grpc_insecure_channel_create(target.c_str(), &channel_args)));
   }
 
   // InsecureCredentials should not be applied to a call.
diff --git a/src/cpp/server/secure_server_credentials.cc b/src/cpp/server/secure_server_credentials.cc
index 3e262dd..32c45e2 100644
--- a/src/cpp/server/secure_server_credentials.cc
+++ b/src/cpp/server/secure_server_credentials.cc
@@ -51,7 +51,8 @@
   }
   grpc_server_credentials* c_creds = grpc_ssl_server_credentials_create(
       options.pem_root_certs.empty() ? nullptr : options.pem_root_certs.c_str(),
-      &pem_key_cert_pairs[0], pem_key_cert_pairs.size());
+      &pem_key_cert_pairs[0], pem_key_cert_pairs.size(),
+      options.force_client_auth);
   return std::shared_ptr<ServerCredentials>(
       new SecureServerCredentials(c_creds));
 }
diff --git a/src/csharp/Grpc.Auth/Grpc.Auth.csproj b/src/csharp/Grpc.Auth/Grpc.Auth.csproj
index afb8204..8e50368 100644
--- a/src/csharp/Grpc.Auth/Grpc.Auth.csproj
+++ b/src/csharp/Grpc.Auth/Grpc.Auth.csproj
@@ -24,13 +24,22 @@
     <ConsolePause>false</ConsolePause>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <DebugType>full</DebugType>
+    <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
     <OutputPath>bin\Release</OutputPath>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
     <ConsolePause>false</ConsolePause>
   </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>C:\keys\Grpc.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="BouncyCastle.Crypto">
       <HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
@@ -79,7 +88,7 @@
     </Compile>
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="GoogleCredential.cs" />
-    <Compile Include="OAuth2InterceptorFactory.cs" />
+    <Compile Include="OAuth2Interceptors.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <ItemGroup>
diff --git a/src/csharp/Grpc.Auth/Grpc.Auth.nuspec b/src/csharp/Grpc.Auth/Grpc.Auth.nuspec
index eeaa49a..2dc10d2 100644
--- a/src/csharp/Grpc.Auth/Grpc.Auth.nuspec
+++ b/src/csharp/Grpc.Auth/Grpc.Auth.nuspec
@@ -20,9 +20,9 @@
     </dependencies>
   </metadata>
   <files>
-    <file src="bin/Release/Grpc.Auth.dll" target="lib/net45" />
-	<file src="bin/Release/Grpc.Auth.pdb" target="lib/net45" />
-	<file src="bin/Release/Grpc.Auth.xml" target="lib/net45" />
+    <file src="bin/ReleaseSigned/Grpc.Auth.dll" target="lib/net45" />
+	<file src="bin/ReleaseSigned/Grpc.Auth.pdb" target="lib/net45" />
+	<file src="bin/ReleaseSigned/Grpc.Auth.xml" target="lib/net45" />
 	<file src="**\*.cs" target="src" />
   </files>
 </package>
diff --git a/src/csharp/Grpc.Auth/OAuth2InterceptorFactory.cs b/src/csharp/Grpc.Auth/OAuth2Interceptors.cs
similarity index 78%
rename from src/csharp/Grpc.Auth/OAuth2InterceptorFactory.cs
rename to src/csharp/Grpc.Auth/OAuth2Interceptors.cs
index 420c4cb..c785ca5 100644
--- a/src/csharp/Grpc.Auth/OAuth2InterceptorFactory.cs
+++ b/src/csharp/Grpc.Auth/OAuth2Interceptors.cs
@@ -47,18 +47,32 @@
 
 namespace Grpc.Auth
 {
-    public static class OAuth2InterceptorFactory
+    public static class OAuth2Interceptors
     {
         /// <summary>
-        /// Creates OAuth2 interceptor.
+        /// Creates OAuth2 interceptor that will obtain access token from GoogleCredentials.
         /// </summary>
-        public static MetadataInterceptorDelegate Create(GoogleCredential googleCredential)
+        public static MetadataInterceptorDelegate FromCredential(GoogleCredential googleCredential)
         {
             var interceptor = new OAuth2Interceptor(googleCredential.InternalCredential, SystemClock.Default);
             return new MetadataInterceptorDelegate(interceptor.InterceptHeaders);
         }
 
         /// <summary>
+        /// Creates OAuth2 interceptor that will use given OAuth2 token.
+        /// </summary>
+        /// <param name="oauth2Token"></param>
+        /// <returns></returns>
+        public static MetadataInterceptorDelegate FromAccessToken(string oauth2Token)
+        {
+            Preconditions.CheckNotNull(oauth2Token);
+            return new MetadataInterceptorDelegate((metadata) =>
+            {
+                metadata.Add(OAuth2Interceptor.CreateBearerTokenHeader(oauth2Token));
+            });
+        }
+
+        /// <summary>
         /// Injects OAuth2 authorization header into initial metadata (= request headers).
         /// </summary>
         private class OAuth2Interceptor
@@ -97,8 +111,15 @@
             public void InterceptHeaders(Metadata metadata)
             {
                 var accessToken = GetAccessToken(CancellationToken.None);
-                metadata.Add(new Metadata.Entry(AuthorizationHeader, Schema + " " + accessToken));
+                metadata.Add(CreateBearerTokenHeader(accessToken));
+            }
+
+            public static Metadata.Entry CreateBearerTokenHeader(string accessToken)
+            {
+                return new Metadata.Entry(AuthorizationHeader, Schema + " " + accessToken);
             }
         }
+
+
     }
 }
diff --git a/src/csharp/Grpc.Auth/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Auth/Properties/AssemblyInfo.cs
index 70cb32d..83396c5 100644
--- a/src/csharp/Grpc.Auth/Properties/AssemblyInfo.cs
+++ b/src/csharp/Grpc.Auth/Properties/AssemblyInfo.cs
@@ -9,5 +9,3 @@
 [assembly: AssemblyCopyright("Google Inc.  All rights reserved.")]
 [assembly: AssemblyTrademark("")]
 [assembly: AssemblyCulture("")]
-
-[assembly: InternalsVisibleTo("Grpc.Auth.Tests")]
diff --git a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
index e286ea5..540fe75 100644
--- a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
+++ b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
@@ -209,8 +209,8 @@
         {
             var headers = new Metadata
             {
-                new Metadata.Entry("asciiHeader", "abcdefg"),
-                new Metadata.Entry("binaryHeader-bin", new byte[] { 1, 2, 3, 0, 0xff }),
+                new Metadata.Entry("ascii-header", "abcdefg"),
+                new Metadata.Entry("binary-header-bin", new byte[] { 1, 2, 3, 0, 0xff }),
             };
             var internalCall = new Call<string, string>(ServiceName, EchoMethod, channel, headers);
             var call = Calls.AsyncUnaryCall(internalCall, "ABC", CancellationToken.None);
diff --git a/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj b/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
index 1c4cca8..242a60d 100644
--- a/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
+++ b/src/csharp/Grpc.Core.Tests/Grpc.Core.Tests.csproj
@@ -17,15 +17,22 @@
     <DefineConstants>DEBUG;</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <ConsolePause>false</ConsolePause>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <DebugType>full</DebugType>
+    <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
     <OutputPath>bin\Release</OutputPath>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <ConsolePause>false</ConsolePause>
+  </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>C:\keys\Grpc.snk</AssemblyOriginatorKeyFile>
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="nunit.core">
diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj
index 0d879e9..940a6b8 100644
--- a/src/csharp/Grpc.Core/Grpc.Core.csproj
+++ b/src/csharp/Grpc.Core/Grpc.Core.csproj
@@ -21,15 +21,23 @@
     <DefineConstants>DEBUG;</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <ConsolePause>false</ConsolePause>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <DebugType>full</DebugType>
+    <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
     <OutputPath>bin\Release</OutputPath>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <ConsolePause>false</ConsolePause>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseSigned|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\ReleaseSigned</OutputPath>
+    <DefineConstants>SIGNED</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <SignAssembly>True</SignAssembly>
+    <AssemblyOriginatorKeyFile>C:\keys\Grpc.snk</AssemblyOriginatorKeyFile>
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
diff --git a/src/csharp/Grpc.Core/Grpc.Core.nuspec b/src/csharp/Grpc.Core/Grpc.Core.nuspec
index 5ace6dc..086776f 100644
--- a/src/csharp/Grpc.Core/Grpc.Core.nuspec
+++ b/src/csharp/Grpc.Core/Grpc.Core.nuspec
@@ -21,9 +21,9 @@
     </dependencies>
   </metadata>
   <files>
-    <file src="bin/Release/Grpc.Core.dll" target="lib/net45" />
-	<file src="bin/Release/Grpc.Core.pdb" target="lib/net45" />
-	<file src="bin/Release/Grpc.Core.xml" target="lib/net45" />
+    <file src="bin/ReleaseSigned/Grpc.Core.dll" target="lib/net45" />
+	<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" />
   </files>
 </package>
diff --git a/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs
index 2b3d753..29db85d 100644
--- a/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs
+++ b/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs
@@ -10,4 +10,12 @@
 [assembly: AssemblyTrademark("")]
 [assembly: AssemblyCulture("")]
 
+#if SIGNED
+[assembly: InternalsVisibleTo("Grpc.Core.Tests,PublicKey=" +
+    "00240000048000009400000006020000002400005253413100040000010001002f5797a92c6fcde81bd4098f43" +
+    "0442bb8e12768722de0b0cb1b15e955b32a11352740ee59f2c94c48edc8e177d1052536b8ac651bce11ce5da3a" +
+    "27fc95aff3dc604a6971417453f9483c7b5e836756d5b271bf8f2403fe186e31956148c03d804487cf642f8cc0" +
+    "71394ee9672dfe5b55ea0f95dfd5a7f77d22c962ccf51320d3")]
+#else
 [assembly: InternalsVisibleTo("Grpc.Core.Tests")]
+#endif
\ No newline at end of file
diff --git a/src/csharp/Grpc.Examples.MathClient/Grpc.Examples.MathClient.csproj b/src/csharp/Grpc.Examples.MathClient/Grpc.Examples.MathClient.csproj
index 85996a5..b603e3a 100644
--- a/src/csharp/Grpc.Examples.MathClient/Grpc.Examples.MathClient.csproj
+++ b/src/csharp/Grpc.Examples.MathClient/Grpc.Examples.MathClient.csproj
@@ -19,17 +19,22 @@
     <DefineConstants>DEBUG;</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <Externalconsole>true</Externalconsole>
-    <PlatformTarget>AnyCPU</PlatformTarget>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <DebugType>full</DebugType>
+    <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
     <OutputPath>bin\Release</OutputPath>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <Externalconsole>true</Externalconsole>
-    <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>C:\keys\Grpc.snk</AssemblyOriginatorKeyFile>
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
diff --git a/src/csharp/Grpc.Examples.MathServer/Grpc.Examples.MathServer.csproj b/src/csharp/Grpc.Examples.MathServer/Grpc.Examples.MathServer.csproj
index 6c8856c..5f74b58 100644
--- a/src/csharp/Grpc.Examples.MathServer/Grpc.Examples.MathServer.csproj
+++ b/src/csharp/Grpc.Examples.MathServer/Grpc.Examples.MathServer.csproj
@@ -19,17 +19,22 @@
     <DefineConstants>DEBUG;</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <Externalconsole>true</Externalconsole>
-    <PlatformTarget>AnyCPU</PlatformTarget>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <DebugType>full</DebugType>
+    <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
     <OutputPath>bin\Release</OutputPath>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <Externalconsole>true</Externalconsole>
-    <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>C:\keys\Grpc.snk</AssemblyOriginatorKeyFile>
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
diff --git a/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj b/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj
index d59d751..9a8f780 100644
--- a/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj
+++ b/src/csharp/Grpc.Examples.Tests/Grpc.Examples.Tests.csproj
@@ -19,15 +19,22 @@
     <DefineConstants>DEBUG;</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <ConsolePause>false</ConsolePause>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <DebugType>full</DebugType>
+    <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
     <OutputPath>bin\Release</OutputPath>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <ConsolePause>false</ConsolePause>
+  </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>C:\keys\Grpc.snk</AssemblyOriginatorKeyFile>
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="nunit.framework">
diff --git a/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs b/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs
index 26f332c..242d29a 100644
--- a/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs
+++ b/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs
@@ -65,7 +65,7 @@
             // for header support.
             client.HeaderInterceptor = (metadata) =>
             {
-                metadata.Add(new Metadata.Entry("customHeader", "abcdef"));
+                metadata.Add(new Metadata.Entry("custom-header", "abcdef"));
             };
         }
 
diff --git a/src/csharp/Grpc.Examples/Grpc.Examples.csproj b/src/csharp/Grpc.Examples/Grpc.Examples.csproj
index eaf24a2..c1aa405 100644
--- a/src/csharp/Grpc.Examples/Grpc.Examples.csproj
+++ b/src/csharp/Grpc.Examples/Grpc.Examples.csproj
@@ -19,15 +19,22 @@
     <DefineConstants>DEBUG;</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <ConsolePause>false</ConsolePause>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <DebugType>full</DebugType>
+    <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
     <OutputPath>bin\Release</OutputPath>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <ConsolePause>false</ConsolePause>
+  </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>C:\keys\Grpc.snk</AssemblyOriginatorKeyFile>
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
diff --git a/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj b/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj
index 72e1103..c922ddf 100644
--- a/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj
+++ b/src/csharp/Grpc.HealthCheck.Tests/Grpc.HealthCheck.Tests.csproj
@@ -17,7 +17,6 @@
     <DebugType>full</DebugType>
     <Optimize>false</Optimize>
     <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
   </PropertyGroup>
@@ -25,10 +24,18 @@
     <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
     <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
   </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>C:\keys\Grpc.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="Google.ProtocolBuffers">
       <HintPath>..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.dll</HintPath>
diff --git a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj
index 4ebb644..0b7a7b9 100644
--- a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj
+++ b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.csproj
@@ -18,7 +18,6 @@
     <DebugType>full</DebugType>
     <Optimize>false</Optimize>
     <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
   </PropertyGroup>
@@ -26,10 +25,18 @@
     <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
     <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
   </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>C:\keys\Grpc.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="Google.ProtocolBuffers">
       <HintPath>..\packages\Google.ProtocolBuffers.2.4.1.555\lib\net40\Google.ProtocolBuffers.dll</HintPath>
diff --git a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.nuspec b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.nuspec
index ca35b36..acdfba4 100644
--- a/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.nuspec
+++ b/src/csharp/Grpc.HealthCheck/Grpc.HealthCheck.nuspec
@@ -20,9 +20,9 @@
     </dependencies>
   </metadata>
   <files>
-    <file src="bin/Release/Grpc.HealthCheck.dll" target="lib/net45" />
-	<file src="bin/Release/Grpc.HealthCheck.pdb" target="lib/net45" />
-	<file src="bin/Release/Grpc.HealthCheck.xml" target="lib/net45" />
+    <file src="bin/ReleaseSigned/Grpc.HealthCheck.dll" target="lib/net45" />
+	<file src="bin/ReleaseSigned/Grpc.HealthCheck.pdb" target="lib/net45" />
+	<file src="bin/ReleaseSigned/Grpc.HealthCheck.xml" target="lib/net45" />
 	<file src="**\*.cs" target="src" />
   </files>
 </package>
diff --git a/src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj b/src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj
index 37d53d6..2c38c96 100644
--- a/src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj
+++ b/src/csharp/Grpc.IntegrationTesting.Client/Grpc.IntegrationTesting.Client.csproj
@@ -18,18 +18,25 @@
     <DefineConstants>DEBUG;</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <Externalconsole>true</Externalconsole>
     <PlatformTarget>AnyCPU</PlatformTarget>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <DebugType>full</DebugType>
+    <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
     <OutputPath>bin\Release</OutputPath>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <Externalconsole>true</Externalconsole>
     <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>C:\keys\Grpc.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
   </ItemGroup>
diff --git a/src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj b/src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj
index 0f3b9eb..949ad61 100644
--- a/src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj
+++ b/src/csharp/Grpc.IntegrationTesting.Server/Grpc.IntegrationTesting.Server.csproj
@@ -18,18 +18,25 @@
     <DefineConstants>DEBUG;</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <Externalconsole>true</Externalconsole>
     <PlatformTarget>AnyCPU</PlatformTarget>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <DebugType>full</DebugType>
+    <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
     <OutputPath>bin\Release</OutputPath>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <Externalconsole>true</Externalconsole>
     <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>C:\keys\Grpc.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
   </ItemGroup>
diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
index db2e304..abc27f8 100644
--- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
+++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
@@ -18,18 +18,25 @@
     <DefineConstants>DEBUG;</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <Externalconsole>true</Externalconsole>
     <PlatformTarget>AnyCPU</PlatformTarget>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <DebugType>full</DebugType>
+    <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
     <OutputPath>bin\Release</OutputPath>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <Externalconsole>true</Externalconsole>
     <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>C:\keys\Grpc.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="BouncyCastle.Crypto">
       <HintPath>..\packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll</HintPath>
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
index 4f8a5a5..7411d91 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
@@ -127,7 +127,7 @@
                     {
                         credential = credential.CreateScoped(new[] { AuthScope });
                     }
-                    client.HeaderInterceptor = OAuth2InterceptorFactory.Create(credential);
+                    client.HeaderInterceptor = OAuth2Interceptors.FromCredential(credential);
                 }
 
                 RunTestCaseAsync(options.testCase, client).Wait();
@@ -356,11 +356,7 @@
             Assert.IsTrue(credential.RequestAccessTokenAsync(CancellationToken.None).Result);
             string oauth2Token = credential.Token.AccessToken;
 
-            // Intercept calls with an OAuth2 token obtained out-of-band.
-            client.HeaderInterceptor = new MetadataInterceptorDelegate((metadata) =>
-            {
-                metadata.Add(new Metadata.Entry("Authorization", "Bearer " + oauth2Token));
-            });
+            client.HeaderInterceptor = OAuth2Interceptors.FromAccessToken(oauth2Token);
 
             var request = SimpleRequest.CreateBuilder()
                 .SetFillUsername(true)
@@ -381,13 +377,16 @@
             var credential = GoogleCredential.GetApplicationDefault().CreateScoped(new[] { AuthScope });
             Assert.IsTrue(credential.RequestAccessTokenAsync(CancellationToken.None).Result);
             string oauth2Token = credential.Token.AccessToken;
+            var headerInterceptor = OAuth2Interceptors.FromAccessToken(oauth2Token);
 
             var request = SimpleRequest.CreateBuilder()
                 .SetFillUsername(true)
                 .SetFillOauthScope(true)
                 .Build();
 
-            var response = client.UnaryCall(request, headers: new Metadata { new Metadata.Entry("Authorization", "Bearer " + oauth2Token) });
+            var headers = new Metadata();
+            headerInterceptor(headers);
+            var response = client.UnaryCall(request, headers: headers);
 
             Assert.AreEqual(AuthScopeResponse, response.OauthScope);
             Assert.AreEqual(ServiceAccountUser, response.Username);
diff --git a/src/csharp/Grpc.sln b/src/csharp/Grpc.sln
index 0cd8aae..f19f29c 100644
--- a/src/csharp/Grpc.sln
+++ b/src/csharp/Grpc.sln
@@ -36,58 +36,81 @@
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution

 		Debug|Any CPU = Debug|Any CPU

 		Release|Any CPU = Release|Any CPU

+		ReleaseSigned|Any CPU = ReleaseSigned|Any CPU

 	EndGlobalSection

 	GlobalSection(ProjectConfigurationPlatforms) = postSolution

-		{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

-		{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Debug|Any CPU.Build.0 = Debug|Any CPU

-		{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Release|Any CPU.ActiveCfg = Release|Any CPU

-		{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Release|Any CPU.Build.0 = Release|Any CPU

-		{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

-		{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Debug|Any CPU.Build.0 = Debug|Any CPU

-		{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Release|Any CPU.ActiveCfg = Release|Any CPU

-		{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Release|Any CPU.Build.0 = Release|Any CPU

-		{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

-		{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|Any CPU.Build.0 = Debug|Any CPU

-		{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|Any CPU.ActiveCfg = Release|Any CPU

-		{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|Any CPU.Build.0 = Release|Any CPU

 		{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

 		{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Debug|Any CPU.Build.0 = Debug|Any CPU

 		{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Release|Any CPU.ActiveCfg = Release|Any CPU

 		{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.Release|Any CPU.Build.0 = Release|Any CPU

-		{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

-		{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Debug|Any CPU.Build.0 = Debug|Any CPU

-		{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Release|Any CPU.ActiveCfg = Release|Any CPU

-		{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Release|Any CPU.Build.0 = Release|Any CPU

-		{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

-		{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Debug|Any CPU.Build.0 = Debug|Any CPU

-		{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Release|Any CPU.ActiveCfg = Release|Any CPU

-		{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Release|Any CPU.Build.0 = Release|Any CPU

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

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

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

-		{AA5E328A-8835-49D7-98ED-C29F2B3049F0}.Release|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

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

-		{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

-		{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|Any CPU.Build.0 = Debug|Any CPU

-		{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|Any CPU.ActiveCfg = Release|Any CPU

-		{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|Any CPU.Build.0 = Release|Any CPU

-		{C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

-		{C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|Any CPU.Build.0 = Debug|Any CPU

-		{C61154BA-DD4A-4838-8420-0162A28925E0}.Release|Any CPU.ActiveCfg = Release|Any CPU

-		{C61154BA-DD4A-4838-8420-0162A28925E0}.Release|Any CPU.Build.0 = Release|Any CPU

+		{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU

+		{7DC1433E-3225-42C7-B7EA-546D56E27A4B}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU

 		{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

 		{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Debug|Any CPU.Build.0 = Debug|Any CPU

 		{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Release|Any CPU.ActiveCfg = Release|Any CPU

 		{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.Release|Any CPU.Build.0 = Release|Any CPU

+		{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU

+		{CCC4440E-49F7-4790-B0AF-FEABB0837AE7}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU

+		{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

+		{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Debug|Any CPU.Build.0 = Debug|Any CPU

+		{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Release|Any CPU.ActiveCfg = Release|Any CPU

+		{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.Release|Any CPU.Build.0 = Release|Any CPU

+		{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU

+		{86EC5CB4-4EA2-40A2-8057-86542A0353BB}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU

+		{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

+		{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Debug|Any CPU.Build.0 = Debug|Any CPU

+		{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Release|Any CPU.ActiveCfg = Release|Any CPU

+		{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.Release|Any CPU.Build.0 = Release|Any CPU

+		{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU

+		{143B1C29-C442-4BE0-BF3F-A8F92288AC9F}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU

+		{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

+		{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Debug|Any CPU.Build.0 = Debug|Any CPU

+		{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|Any CPU.ActiveCfg = Release|Any CPU

+		{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.Release|Any CPU.Build.0 = Release|Any CPU

+		{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU

+		{61ECB8EE-0C96-4F8E-B187-8E4D227417C0}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU

+		{C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

+		{C61154BA-DD4A-4838-8420-0162A28925E0}.Debug|Any CPU.Build.0 = Debug|Any CPU

+		{C61154BA-DD4A-4838-8420-0162A28925E0}.Release|Any CPU.ActiveCfg = Release|Any CPU

+		{C61154BA-DD4A-4838-8420-0162A28925E0}.Release|Any CPU.Build.0 = Release|Any CPU

+		{C61154BA-DD4A-4838-8420-0162A28925E0}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU

+		{C61154BA-DD4A-4838-8420-0162A28925E0}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU

+		{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

+		{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Debug|Any CPU.Build.0 = Debug|Any CPU

+		{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Release|Any CPU.ActiveCfg = Release|Any CPU

+		{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.Release|Any CPU.Build.0 = Release|Any CPU

+		{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU

+		{3D166931-BA2D-416E-95A3-D36E8F6E90B9}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU

+		{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

+		{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Debug|Any CPU.Build.0 = Debug|Any CPU

+		{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Release|Any CPU.ActiveCfg = Release|Any CPU

+		{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.Release|Any CPU.Build.0 = Release|Any CPU

+		{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU

+		{A654F3B8-E859-4E6A-B30D-227527DBEF0D}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU

+		{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

+		{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Debug|Any CPU.Build.0 = Debug|Any CPU

+		{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|Any CPU.ActiveCfg = Release|Any CPU

+		{BF62FE08-373A-43D6-9D73-41CAA38B7011}.Release|Any CPU.Build.0 = Release|Any CPU

+		{BF62FE08-373A-43D6-9D73-41CAA38B7011}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU

+		{BF62FE08-373A-43D6-9D73-41CAA38B7011}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|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

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

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

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

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

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

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

+		{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

 		{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

 		{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}.Debug|Any CPU.Build.0 = Debug|Any CPU

 		{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}.Release|Any CPU.ActiveCfg = Release|Any CPU

 		{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}.Release|Any CPU.Build.0 = Release|Any CPU

-	EndGlobalSection

-	GlobalSection(NestedProjects) = preSolution

+		{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}.ReleaseSigned|Any CPU.ActiveCfg = ReleaseSigned|Any CPU

+		{F8C6D937-C44B-4EE3-A431-B0FBAEACE47D}.ReleaseSigned|Any CPU.Build.0 = ReleaseSigned|Any CPU

 	EndGlobalSection

 	GlobalSection(SolutionProperties) = preSolution

 		HideSolutionNode = FALSE

diff --git a/src/csharp/build_packages.bat b/src/csharp/build_packages.bat
index c3e5fe8..9e1253b 100644
--- a/src/csharp/build_packages.bat
+++ b/src/csharp/build_packages.bat
@@ -12,7 +12,7 @@
 @call buildall.bat || goto :error
 endlocal
 
-@call buildall.bat || goto :error
+@call buildall.bat BUILD_SIGNED || goto :error
 
 %NUGET% pack ..\..\vsprojects\nuget_package\grpc.native.csharp_ext.nuspec -Version %CORE_VERSION% || goto :error
 %NUGET% pack Grpc.Auth\Grpc.Auth.nuspec -Symbols -Version %VERSION% || goto :error
diff --git a/src/csharp/buildall.bat b/src/csharp/buildall.bat
index 16860ae..e73feb8 100644
--- a/src/csharp/buildall.bat
+++ b/src/csharp/buildall.bat
@@ -13,6 +13,11 @@
 
 msbuild Grpc.sln /p:Configuration=Debug || goto :error
 msbuild Grpc.sln /p:Configuration=Release || goto :error
+
+if "%1" == "BUILD_SIGNED" (
+msbuild Grpc.sln /p:Configuration=ReleaseSigned || goto :error
+)
+
 endlocal
 
 goto :EOF
diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c
index 6d15124..49a0471 100644
--- a/src/csharp/ext/grpc_csharp_ext.c
+++ b/src/csharp/ext/grpc_csharp_ext.c
@@ -366,8 +366,9 @@
 /* Channel */
 
 GPR_EXPORT grpc_channel *GPR_CALLTYPE
+
 grpcsharp_insecure_channel_create(const char *target, const grpc_channel_args *args) {
-  return grpc_channel_create(target, args);
+  return grpc_insecure_channel_create(target, args);
 }
 
 GPR_EXPORT void GPR_CALLTYPE grpcsharp_channel_destroy(grpc_channel *channel) {
@@ -790,8 +791,9 @@
       key_cert_pairs[i].private_key = key_cert_pair_private_key_array[i];
     }
   }
+  /* TODO: Add a force_client_auth parameter and pass it here. */
   creds = grpc_ssl_server_credentials_create(pem_root_certs, key_cert_pairs,
-                                             num_key_cert_pairs);
+                                             num_key_cert_pairs, 0);
   gpr_free(key_cert_pairs);
   return creds;
 }
diff --git a/src/csharp/keys/Grpc.public.snk b/src/csharp/keys/Grpc.public.snk
new file mode 100644
index 0000000..bac3046
--- /dev/null
+++ b/src/csharp/keys/Grpc.public.snk
Binary files differ
diff --git a/src/csharp/keys/README.md b/src/csharp/keys/README.md
new file mode 100644
index 0000000..f3e9a3c
--- /dev/null
+++ b/src/csharp/keys/README.md
@@ -0,0 +1,5 @@
+Contents
+--------
+
+- Grpc.public.snk:
+  Public key to verify strong name of gRPC assemblies.
\ No newline at end of file
diff --git a/src/node/ext/channel.cc b/src/node/ext/channel.cc
index 0b7333e..c43b55f 100644
--- a/src/node/ext/channel.cc
+++ b/src/node/ext/channel.cc
@@ -105,7 +105,7 @@
     NanUtf8String *host = new NanUtf8String(args[0]);
     NanUtf8String *host_override = NULL;
     if (args[1]->IsUndefined()) {
-      wrapped_channel = grpc_channel_create(**host, NULL);
+      wrapped_channel = grpc_insecure_channel_create(**host, NULL);
     } else if (args[1]->IsObject()) {
       grpc_credentials *creds = NULL;
       Handle<Object> args_hash(args[1]->ToObject()->Clone());
@@ -150,7 +150,7 @@
         }
       }
       if (creds == NULL) {
-        wrapped_channel = grpc_channel_create(**host, &channel_args);
+        wrapped_channel = grpc_insecure_channel_create(**host, &channel_args);
       } else {
         wrapped_channel =
             grpc_secure_channel_create(creds, **host, &channel_args);
diff --git a/src/node/ext/server_credentials.cc b/src/node/ext/server_credentials.cc
index 66aaa33..c4a93a6 100644
--- a/src/node/ext/server_credentials.cc
+++ b/src/node/ext/server_credentials.cc
@@ -138,8 +138,10 @@
     return NanThrowTypeError("createSsl's third argument must be a Buffer");
   }
   key_cert_pair.cert_chain = ::node::Buffer::Data(args[2]);
+  // TODO Add a force_client_auth parameter and pass it as the last parameter
+  // here.
   NanReturnValue(WrapStruct(
-      grpc_ssl_server_credentials_create(root_certs, &key_cert_pair, 1)));
+      grpc_ssl_server_credentials_create(root_certs, &key_cert_pair, 1, 0)));
 }
 
 }  // namespace node
diff --git a/src/node/index.js b/src/node/index.js
index d81e780..b26ab35 100644
--- a/src/node/index.js
+++ b/src/node/index.js
@@ -48,7 +48,7 @@
  * @param {ProtoBuf.Reflect.Namespace} value The ProtoBuf object to load.
  * @return {Object<string, *>} The resulting gRPC object
  */
-function loadObject(value) {
+exports.loadObject = function loadObject(value) {
   var result = {};
   if (value.className === 'Namespace') {
     _.each(value.children, function(child) {
@@ -62,7 +62,9 @@
   } else {
     return value;
   }
-}
+};
+
+var loadObject = exports.loadObject;
 
 /**
  * Load a gRPC object from a .proto file.
@@ -71,7 +73,7 @@
  *     'json'. Defaults to 'proto'
  * @return {Object<string, *>} The resulting gRPC object
  */
-function load(filename, format) {
+exports.load = function load(filename, format) {
   if (!format) {
     format = 'proto';
   }
@@ -88,7 +90,7 @@
   }
 
   return loadObject(builder.ns);
-}
+};
 
 /**
  * Get a function that a client can use to update metadata with authentication
@@ -97,7 +99,7 @@
  * @param {Object} credential The credential object to use
  * @return {function(Object, callback)} Metadata updater function
  */
-function getGoogleAuthDelegate(credential) {
+exports.getGoogleAuthDelegate = function getGoogleAuthDelegate(credential) {
   /**
    * Update a metadata object with authentication information.
    * @param {string} authURI The uri to authenticate to
@@ -120,20 +122,10 @@
       callback(null, metadata);
     });
   };
-}
+};
 
 /**
- * See docs for loadObject
- */
-exports.loadObject = loadObject;
-
-/**
- * See docs for load
- */
-exports.load = load;
-
-/**
- * See docs for Server
+ * @see module:src/server.Server
  */
 exports.Server = server.Server;
 
@@ -141,6 +133,7 @@
  * Status name to code number mapping
  */
 exports.status = grpc.status;
+
 /**
  * Call error name to code number mapping
  */
@@ -156,6 +149,7 @@
  */
 exports.ServerCredentials = grpc.ServerCredentials;
 
-exports.getGoogleAuthDelegate = getGoogleAuthDelegate;
-
+/**
+ * @see module:src/client.makeClientConstructor
+ */
 exports.makeGenericClientConstructor = client.makeClientConstructor;
diff --git a/src/node/jsdoc_conf.json b/src/node/jsdoc_conf.json
new file mode 100644
index 0000000..876a8e1
--- /dev/null
+++ b/src/node/jsdoc_conf.json
@@ -0,0 +1,22 @@
+{
+  "tags": {
+    "allowUnknownTags": true
+  },
+  "source": {
+    "include": [ "index.js", "src" ],
+    "includePattern": ".+\\.js(doc)?$",
+    "excludePattern": "(^|\\/|\\\\)_"
+  },
+  "opts": {
+    "package": "package.json",
+    "readme": "README.md"
+  },
+  "plugins": [],
+  "templates": {
+    "cleverLinks": false,
+    "monospaceLinks": false,
+    "default": {
+      "outputSourceFiles": true
+    }
+  }
+}
diff --git a/src/node/package.json b/src/node/package.json
index 1caf158..756d41b 100644
--- a/src/node/package.json
+++ b/src/node/package.json
@@ -21,7 +21,8 @@
   },
   "scripts": {
     "lint": "node ./node_modules/jshint/bin/jshint src test examples interop index.js",
-    "test": "node ./node_modules/mocha/bin/mocha && npm run-script lint"
+    "test": "node ./node_modules/mocha/bin/mocha && npm run-script lint",
+    "gen_docs": "./node_modules/.bin/jsdoc -c jsdoc_conf.json"
   },
   "dependencies": {
     "bindings": "^1.2.0",
@@ -32,6 +33,7 @@
   "devDependencies": {
     "async": "^0.9.0",
     "google-auth-library": "^0.9.2",
+    "jsdoc": "^3.3.2",
     "jshint": "^2.5.0",
     "minimist": "^1.1.0",
     "mocha": "~1.21.0",
diff --git a/src/node/src/client.js b/src/node/src/client.js
index d89c656..f843669 100644
--- a/src/node/src/client.js
+++ b/src/node/src/client.js
@@ -31,6 +31,11 @@
  *
  */
 
+/**
+ * Server module
+ * @module
+ */
+
 'use strict';
 
 var _ = require('lodash');
@@ -72,6 +77,7 @@
 /**
  * Attempt to write the given chunk. Calls the callback when done. This is an
  * implementation of a method needed for implementing stream.Writable.
+ * @access private
  * @param {Buffer} chunk The chunk to write
  * @param {string} encoding Ignored
  * @param {function(Error=)} callback Called when the write is complete
@@ -110,6 +116,7 @@
 
 /**
  * Read the next object from the stream.
+ * @access private
  * @param {*} size Ignored because we use objectMode=true
  */
 function _read(size) {
@@ -519,7 +526,7 @@
  * @param {string} serviceName The name of the service
  * @return {function(string, Object)} New client constructor
  */
-function makeClientConstructor(methods, serviceName) {
+exports.makeClientConstructor = function(methods, serviceName) {
   /**
    * Create a client with the given methods
    * @constructor
@@ -568,7 +575,7 @@
   });
 
   return Client;
-}
+};
 
 /**
  * Creates a constructor for clients for the given service
@@ -576,22 +583,18 @@
  *     for
  * @return {function(string, Object)} New client constructor
  */
-function makeProtobufClientConstructor(service) {
+exports.makeProtobufClientConstructor =  function(service) {
   var method_attrs = common.getProtobufServiceAttrs(service, service.name);
-  var Client = makeClientConstructor(method_attrs);
+  var Client = exports.makeClientConstructor(method_attrs);
   Client.service = service;
-
   return Client;
-}
-
-exports.makeClientConstructor = makeClientConstructor;
-
-exports.makeProtobufClientConstructor = makeProtobufClientConstructor;
+};
 
 /**
- * See docs for client.status
+ * Map of status code names to status codes
  */
 exports.status = grpc.status;
+
 /**
  * See docs for client.callError
  */
diff --git a/src/node/src/common.js b/src/node/src/common.js
index feaa859..5551ebe 100644
--- a/src/node/src/common.js
+++ b/src/node/src/common.js
@@ -31,6 +31,10 @@
  *
  */
 
+/**
+ * @module
+ */
+
 'use strict';
 
 var _ = require('lodash');
@@ -40,7 +44,7 @@
  * @param {function()} cls The constructor of the message type to deserialize
  * @return {function(Buffer):cls} The deserialization function
  */
-function deserializeCls(cls) {
+exports.deserializeCls = function deserializeCls(cls) {
   /**
    * Deserialize a buffer to a message object
    * @param {Buffer} arg_buf The buffer to deserialize
@@ -51,14 +55,16 @@
     // and longs as strings (second argument)
     return cls.decode(arg_buf).toRaw(false, true);
   };
-}
+};
+
+var deserializeCls = exports.deserializeCls;
 
 /**
  * Get a function that serializes objects to a buffer by protobuf class.
  * @param {function()} Cls The constructor of the message type to serialize
  * @return {function(Cls):Buffer} The serialization function
  */
-function serializeCls(Cls) {
+exports.serializeCls = function serializeCls(Cls) {
   /**
    * Serialize an object to a Buffer
    * @param {Object} arg The object to serialize
@@ -67,14 +73,16 @@
   return function serialize(arg) {
     return new Buffer(new Cls(arg).encode().toBuffer());
   };
-}
+};
+
+var serializeCls = exports.serializeCls;
 
 /**
  * Get the fully qualified (dotted) name of a ProtoBuf.Reflect value.
  * @param {ProtoBuf.Reflect.Namespace} value The value to get the name of
  * @return {string} The fully qualified name of the value
  */
-function fullyQualifiedName(value) {
+exports.fullyQualifiedName = function fullyQualifiedName(value) {
   if (value === null || value === undefined) {
     return '';
   }
@@ -89,7 +97,9 @@
     }
   }
   return name;
-}
+};
+
+var fullyQualifiedName = exports.fullyQualifiedName;
 
 /**
  * Wrap a function to pass null-like values through without calling it. If no
@@ -97,7 +107,7 @@
  * @param {?function} func The function to wrap
  * @return {function} The wrapped function
  */
-function wrapIgnoreNull(func) {
+exports.wrapIgnoreNull = function wrapIgnoreNull(func) {
   if (!func) {
     return _.identity;
   }
@@ -107,14 +117,14 @@
     }
     return func(arg);
   };
-}
+};
 
 /**
  * Return a map from method names to method attributes for the service.
  * @param {ProtoBuf.Reflect.Service} service The service to get attributes for
  * @return {Object} The attributes map
  */
-function getProtobufServiceAttrs(service) {
+exports.getProtobufServiceAttrs = function getProtobufServiceAttrs(service) {
   var prefix = '/' + fullyQualifiedName(service) + '/';
   return _.object(_.map(service.children, function(method) {
     return [_.camelCase(method.name), {
@@ -127,26 +137,4 @@
       responseDeserialize: deserializeCls(method.resolvedResponseType.build())
     }];
   }));
-}
-
-/**
- * See docs for deserializeCls
- */
-exports.deserializeCls = deserializeCls;
-
-/**
- * See docs for serializeCls
- */
-exports.serializeCls = serializeCls;
-
-/**
- * See docs for fullyQualifiedName
- */
-exports.fullyQualifiedName = fullyQualifiedName;
-
-/**
- * See docs for wrapIgnoreNull
- */
-exports.wrapIgnoreNull = wrapIgnoreNull;
-
-exports.getProtobufServiceAttrs = getProtobufServiceAttrs;
+};
diff --git a/src/node/src/server.js b/src/node/src/server.js
index e876313..9fbd1ee 100644
--- a/src/node/src/server.js
+++ b/src/node/src/server.js
@@ -31,6 +31,11 @@
  *
  */
 
+/**
+ * Server module
+ * @module
+ */
+
 'use strict';
 
 var _ = require('lodash');
@@ -50,6 +55,7 @@
 
 /**
  * Handle an error on a call by sending it as a status
+ * @access private
  * @param {grpc.Call} call The call to send the error on
  * @param {Object} error The error object
  */
@@ -82,6 +88,7 @@
 /**
  * Wait for the client to close, then emit a cancelled event if the client
  * cancelled.
+ * @access private
  * @param {grpc.Call} call The call object to wait on
  * @param {EventEmitter} emitter The event emitter to emit the cancelled event
  *     on
@@ -102,6 +109,7 @@
 
 /**
  * Send a response to a unary or client streaming call.
+ * @access private
  * @param {grpc.Call} call The call to respond on
  * @param {*} value The value to respond with
  * @param {function(*):Buffer=} serialize Serialization function for the
@@ -130,6 +138,7 @@
 /**
  * Initialize a writable stream. This is used for both the writable and duplex
  * stream constructors.
+ * @access private
  * @param {Writable} stream The stream to set up
  * @param {function(*):Buffer=} Serialization function for responses
  */
@@ -203,6 +212,7 @@
 /**
  * Initialize a readable stream. This is used for both the readable and duplex
  * stream constructors.
+ * @access private
  * @param {Readable} stream The stream to initialize
  * @param {function(Buffer):*=} deserialize Deserialization function for
  *     incoming data.
@@ -242,6 +252,7 @@
 /**
  * Start writing a chunk of data. This is an implementation of a method required
  * for implementing stream.Writable.
+ * @access private
  * @param {Buffer} chunk The chunk of data to write
  * @param {string} encoding Ignored
  * @param {function(Error=)} callback Callback to indicate that the write is
@@ -266,6 +277,11 @@
 
 ServerWritableStream.prototype._write = _write;
 
+/**
+ * Send the initial metadata for a writable stream.
+ * @param {Object<String, Array<(String|Buffer)>>} responseMetadata Metadata
+ *   to send
+ */
 function sendMetadata(responseMetadata) {
   /* jshint validthis: true */
   if (!this.call.metadataSent) {
@@ -281,6 +297,10 @@
   }
 }
 
+/**
+ * @inheritdoc
+ * @alias module:src/server~ServerWritableStream#sendMetadata
+ */
 ServerWritableStream.prototype.sendMetadata = sendMetadata;
 
 util.inherits(ServerReadableStream, Readable);
@@ -301,6 +321,7 @@
 /**
  * Start reading from the gRPC data source. This is an implementation of a
  * method required for implementing stream.Readable
+ * @access private
  * @param {number} size Ignored
  */
 function _read(size) {
@@ -388,6 +409,7 @@
 
 /**
  * Fully handle a unary call
+ * @access private
  * @param {grpc.Call} call The call to handle
  * @param {Object} handler Request handler object for the method that was called
  * @param {Object} metadata Metadata from the client
@@ -442,6 +464,7 @@
 
 /**
  * Fully handle a server streaming call
+ * @access private
  * @param {grpc.Call} call The call to handle
  * @param {Object} handler Request handler object for the method that was called
  * @param {Object} metadata Metadata from the client
@@ -470,6 +493,7 @@
 
 /**
  * Fully handle a client streaming call
+ * @access private
  * @param {grpc.Call} call The call to handle
  * @param {Object} handler Request handler object for the method that was called
  * @param {Object} metadata Metadata from the client
@@ -504,6 +528,7 @@
 
 /**
  * Fully handle a bidirectional streaming call
+ * @access private
  * @param {grpc.Call} call The call to handle
  * @param {Object} handler Request handler object for the method that was called
  * @param {Object} metadata Metadata from the client
@@ -587,7 +612,8 @@
     }
     server.requestCall(handleNewCall);
   };
-  /** Shuts down the server.
+  /**
+   * Shuts down the server.
    */
   this.shutdown = function() {
     server.shutdown();
@@ -621,6 +647,15 @@
   return true;
 };
 
+/**
+ * Add a service to the server, with a corresponding implementation. If you are
+ * generating this from a proto file, you should instead use
+ * addProtoService.
+ * @param {Object<String, *>} service The service descriptor, as
+ *     {@link module:src/common.getProtobufServiceAttrs} returns
+ * @param {Object<String, function>} implementation Map of method names to
+ *     method implementation for the provided service.
+ */
 Server.prototype.addService = function(service, implementation) {
   if (this.started) {
     throw new Error('Can\'t add a service to a started server.');
@@ -658,6 +693,12 @@
   });
 };
 
+/**
+ * Add a proto service to the server, with a corresponding implementation
+ * @param {Protobuf.Reflect.Service} service The proto service descriptor
+ * @param {Object<String, function>} implementation Map of method names to
+ *     method implementation for the provided service.
+ */
 Server.prototype.addProtoService = function(service, implementation) {
   this.addService(common.getProtobufServiceAttrs(service), implementation);
 };
@@ -681,6 +722,6 @@
 };
 
 /**
- * See documentation for Server
+ * @see module:src/server~Server
  */
 exports.Server = Server;
diff --git a/src/objective-c/GRPCClient/private/GRPCUnsecuredChannel.m b/src/objective-c/GRPCClient/private/GRPCUnsecuredChannel.m
index d27f7ca..8518f78 100644
--- a/src/objective-c/GRPCClient/private/GRPCUnsecuredChannel.m
+++ b/src/objective-c/GRPCClient/private/GRPCUnsecuredChannel.m
@@ -38,7 +38,7 @@
 @implementation GRPCUnsecuredChannel
 
 - (instancetype)initWithHost:(NSString *)host {
-  return (self = [super initWithChannel:grpc_channel_create(host.UTF8String, NULL)]);
+  return (self = [super initWithChannel:grpc_insecure_channel_create(host.UTF8String, NULL)]);
 }
 
 @end
diff --git a/src/php/ext/grpc/call.c b/src/php/ext/grpc/call.c
index b67bae7..1f76c73 100644
--- a/src/php/ext/grpc/call.c
+++ b/src/php/ext/grpc/call.c
@@ -473,6 +473,16 @@
 }
 
 /**
+ * Get the endpoint this call/stream is connected to
+ * @return string The URI of the endpoint
+ */
+PHP_METHOD(Call, getPeer) {
+  wrapped_grpc_call *call =
+      (wrapped_grpc_call *)zend_object_store_get_object(getThis() TSRMLS_CC);
+  RETURN_STRING(grpc_call_get_peer(call->wrapped), 1);
+}
+
+/**
  * Cancel the call. This will cause the call to end with STATUS_CANCELLED if it
  * has not already ended with another status.
  */
@@ -485,7 +495,9 @@
 static zend_function_entry call_methods[] = {
     PHP_ME(Call, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
     PHP_ME(Call, startBatch, NULL, ZEND_ACC_PUBLIC)
-    PHP_ME(Call, cancel, NULL, ZEND_ACC_PUBLIC) PHP_FE_END};
+    PHP_ME(Call, getPeer, NULL, ZEND_ACC_PUBLIC)
+    PHP_ME(Call, cancel, NULL, ZEND_ACC_PUBLIC)
+    PHP_FE_END};
 
 void grpc_init_call(TSRMLS_D) {
   zend_class_entry ce;
diff --git a/src/php/ext/grpc/channel.c b/src/php/ext/grpc/channel.c
index b8262db..7d8a6f8 100644
--- a/src/php/ext/grpc/channel.c
+++ b/src/php/ext/grpc/channel.c
@@ -152,7 +152,7 @@
   override = target;
   override_len = target_length;
   if (args_array == NULL) {
-    channel->wrapped = grpc_channel_create(target, NULL);
+    channel->wrapped = grpc_insecure_channel_create(target, NULL);
   } else {
     array_hash = Z_ARRVAL_P(args_array);
     if (zend_hash_find(array_hash, "credentials", sizeof("credentials"),
@@ -182,7 +182,7 @@
     }
     php_grpc_read_args_array(args_array, &args);
     if (creds == NULL) {
-      channel->wrapped = grpc_channel_create(target, &args);
+      channel->wrapped = grpc_insecure_channel_create(target, &args);
     } else {
       gpr_log(GPR_DEBUG, "Initialized secure channel");
       channel->wrapped =
@@ -195,6 +195,16 @@
 }
 
 /**
+ * Get the endpoint this call/stream is connected to
+ * @return string The URI of the endpoint
+ */
+PHP_METHOD(Channel, getTarget) {
+  wrapped_grpc_channel *channel =
+      (wrapped_grpc_channel *)zend_object_store_get_object(getThis() TSRMLS_CC);
+  RETURN_STRING(grpc_channel_get_target(channel->wrapped), 1);
+}
+
+/**
  * Close the channel
  */
 PHP_METHOD(Channel, close) {
@@ -208,7 +218,9 @@
 
 static zend_function_entry channel_methods[] = {
     PHP_ME(Channel, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
-    PHP_ME(Channel, close, NULL, ZEND_ACC_PUBLIC) PHP_FE_END};
+    PHP_ME(Channel, getTarget, NULL, ZEND_ACC_PUBLIC)
+    PHP_ME(Channel, close, NULL, ZEND_ACC_PUBLIC)
+    PHP_FE_END};
 
 void grpc_init_channel(TSRMLS_D) {
   zend_class_entry ce;
diff --git a/src/php/ext/grpc/server_credentials.c b/src/php/ext/grpc/server_credentials.c
index 4c4a598..e9183c4 100644
--- a/src/php/ext/grpc/server_credentials.c
+++ b/src/php/ext/grpc/server_credentials.c
@@ -115,8 +115,10 @@
                          "createSsl expects 3 strings", 1 TSRMLS_CC);
     return;
   }
-  grpc_server_credentials *creds =
-      grpc_ssl_server_credentials_create(pem_root_certs, &pem_key_cert_pair, 1);
+  /* 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);
   zval *creds_object = grpc_php_wrap_server_credentials(creds);
   RETURN_DESTROY_ZVAL(creds_object);
 }
diff --git a/src/php/lib/Grpc/AbstractCall.php b/src/php/lib/Grpc/AbstractCall.php
index 5b28417..3505722 100644
--- a/src/php/lib/Grpc/AbstractCall.php
+++ b/src/php/lib/Grpc/AbstractCall.php
@@ -68,6 +68,13 @@
   }
 
   /**
+   * @return string The URI of the endpoint.
+   */
+  public function getPeer() {
+    return $this->call->getPeer();
+  }
+
+  /**
    * Cancels the call
    */
   public function cancel() {
diff --git a/src/php/lib/Grpc/BaseStub.php b/src/php/lib/Grpc/BaseStub.php
index 8c438e4..a0c6779 100755
--- a/src/php/lib/Grpc/BaseStub.php
+++ b/src/php/lib/Grpc/BaseStub.php
@@ -68,6 +68,13 @@
   }
 
   /**
+   * @return string The URI of the endpoint.
+   */
+  public function getTarget() {
+    return $this->channel->getTarget();
+  }
+
+  /**
    * Close the communication channel associated with this stub
    */
   public function close() {
diff --git a/src/php/tests/generated_code/AbstractGeneratedCodeTest.php b/src/php/tests/generated_code/AbstractGeneratedCodeTest.php
index 6102aaf..8b7e67f 100644
--- a/src/php/tests/generated_code/AbstractGeneratedCodeTest.php
+++ b/src/php/tests/generated_code/AbstractGeneratedCodeTest.php
@@ -43,7 +43,9 @@
     $div_arg = new math\DivArgs();
     $div_arg->setDividend(7);
     $div_arg->setDivisor(4);
-    list($response, $status) = self::$client->Div($div_arg)->wait();
+    $call = self::$client->Div($div_arg);
+    $this->assertTrue(is_string($call->getPeer()));
+    list($response, $status) = $call->wait();
     $this->assertSame(1, $response->getQuotient());
     $this->assertSame(3, $response->getRemainder());
     $this->assertSame(\Grpc\STATUS_OK, $status->code);
@@ -53,6 +55,7 @@
     $fib_arg = new math\FibArgs();
     $fib_arg->setLimit(7);
     $call = self::$client->Fib($fib_arg);
+    $this->assertTrue(is_string($call->getPeer()));
     $result_array = iterator_to_array($call->responses());
     $extract_num = function($num){
       return $num->getNum();
@@ -72,6 +75,7 @@
       }
     };
     $call = self::$client->Sum($num_iter());
+    $this->assertTrue(is_string($call->getPeer()));
     list($response, $status) = $call->wait();
     $this->assertSame(21, $response->getNum());
     $this->assertSame(\Grpc\STATUS_OK, $status->code);
@@ -79,6 +83,7 @@
 
   public function testBidiStreaming() {
     $call = self::$client->DivMany();
+    $this->assertTrue(is_string($call->getPeer()));
     for ($i = 0; $i < 7; $i++) {
       $div_arg = new math\DivArgs();
       $div_arg->setDividend(2 * $i + 1);
diff --git a/src/php/tests/interop/interop_client.php b/src/php/tests/interop/interop_client.php
index 2041577..44e6242 100755
--- a/src/php/tests/interop/interop_client.php
+++ b/src/php/tests/interop/interop_client.php
@@ -332,10 +332,11 @@
   $opts['update_metadata'] = $auth->getUpdateMetadataFunc();
 }
 
-$stub = new grpc\testing\TestServiceClient(
-    new Grpc\BaseStub(
-        $server_address,
-        $opts));
+$internal_stub = new Grpc\BaseStub($server_address, $opts);
+hardAssert(is_string($internal_stub->getTarget()),
+           'Unexpected target URI value');
+
+$stub = new grpc\testing\TestServiceClient($internal_stub);
 
 echo "Connecting to $server_address\n";
 echo "Running test case $args[test_case]\n";
diff --git a/src/php/tests/unit_tests/CallTest.php b/src/php/tests/unit_tests/CallTest.php
index 77a2d86..caff15e 100755
--- a/src/php/tests/unit_tests/CallTest.php
+++ b/src/php/tests/unit_tests/CallTest.php
@@ -79,4 +79,8 @@
     $result = $this->call->startBatch($batch);
     $this->assertTrue($result->send_metadata);
   }
+
+  public function testGetPeer() {
+    $this->assertTrue(is_string($this->call->getPeer()));
+  }
 }
diff --git a/src/php/tests/unit_tests/EndToEndTest.php b/src/php/tests/unit_tests/EndToEndTest.php
index 2980dca..27e27cd 100755
--- a/src/php/tests/unit_tests/EndToEndTest.php
+++ b/src/php/tests/unit_tests/EndToEndTest.php
@@ -34,8 +34,8 @@
 class EndToEndTest extends PHPUnit_Framework_TestCase{
   public function setUp() {
     $this->server = new Grpc\Server([]);
-    $port = $this->server->addHttp2Port('0.0.0.0:0');
-    $this->channel = new Grpc\Channel('localhost:' . $port, []);
+    $this->port = $this->server->addHttp2Port('0.0.0.0:0');
+    $this->channel = new Grpc\Channel('localhost:' . $this->port, []);
     $this->server->start();
   }
 
@@ -149,4 +149,8 @@
     unset($call);
     unset($server_call);
   }
+
+  public function testGetTarget() {
+    $this->assertTrue(is_string($this->channel->getTarget()));
+  }
 }
diff --git a/src/python/src/grpc/_adapter/_c/types/channel.c b/src/python/src/grpc/_adapter/_c/types/channel.c
index c235597..feb256c 100644
--- a/src/python/src/grpc/_adapter/_c/types/channel.c
+++ b/src/python/src/grpc/_adapter/_c/types/channel.c
@@ -104,7 +104,7 @@
   if (creds) {
     self->c_chan = grpc_secure_channel_create(creds->c_creds, target, &c_args);
   } else {
-    self->c_chan = grpc_channel_create(target, &c_args);
+    self->c_chan = grpc_insecure_channel_create(target, &c_args);
   }
   pygrpc_discard_channel_args(c_args);
   return self;
diff --git a/src/python/src/grpc/_adapter/_c/types/server_credentials.c b/src/python/src/grpc/_adapter/_c/types/server_credentials.c
index f22edbf..f6859b7 100644
--- a/src/python/src/grpc/_adapter/_c/types/server_credentials.c
+++ b/src/python/src/grpc/_adapter/_c/types/server_credentials.c
@@ -128,8 +128,10 @@
   }
 
   self = (ServerCredentials *)type->tp_alloc(type, 0);
+  /* TODO: Add a force_client_auth parameter in the python object and pass it
+     here as the last arg. */
   self->c_creds = grpc_ssl_server_credentials_create(
-      root_certs, key_cert_pairs, num_key_cert_pairs);
+      root_certs, key_cert_pairs, num_key_cert_pairs, 0);
   gpr_free(key_cert_pairs);
   return self;
 }
diff --git a/src/python/src/grpc/_adapter/_low_test.py b/src/python/src/grpc/_adapter/_low_test.py
index a49cd00..9a8edfa 100644
--- a/src/python/src/grpc/_adapter/_low_test.py
+++ b/src/python/src/grpc/_adapter/_low_test.py
@@ -97,7 +97,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/src/grpc/_links/_proto_scenarios.py b/src/python/src/grpc/_links/_proto_scenarios.py
index ccf3c29..320c0e0 100644
--- a/src/python/src/grpc/_links/_proto_scenarios.py
+++ b/src/python/src/grpc/_links/_proto_scenarios.py
@@ -33,6 +33,7 @@
 import threading
 
 from grpc._junkdrawer import math_pb2
+from grpc.framework.common import test_constants
 
 
 class ProtoScenario(object):
@@ -219,10 +220,9 @@
 class BidirectionallyStreamingScenario(ProtoScenario):
   """A scenario that transmits no protocol buffers in either direction."""
 
-  _STREAM_LENGTH = 200
   _REQUESTS = tuple(
       math_pb2.DivArgs(dividend=59 + index, divisor=7 + index)
-      for index in range(_STREAM_LENGTH))
+      for index in range(test_constants.STREAM_LENGTH))
 
   def __init__(self):
     self._lock = threading.Lock()
diff --git a/src/python/src/grpc/framework/common/test_constants.py b/src/python/src/grpc/framework/common/test_constants.py
index 237b875..3126d0d 100644
--- a/src/python/src/grpc/framework/common/test_constants.py
+++ b/src/python/src/grpc/framework/common/test_constants.py
@@ -35,3 +35,9 @@
 # Absurdly large value for maximum duration in seconds for should-not-time-out
 # RPCs made during tests.
 LONG_TIMEOUT = 3000
+
+# The number of payloads to transmit in streaming tests.
+STREAM_LENGTH = 200
+
+# The size of thread pools to use in tests.
+POOL_SIZE = 10
diff --git a/src/ruby/ext/grpc/rb_call.c b/src/ruby/ext/grpc/rb_call.c
index bfb9f6f..a7607a8 100644
--- a/src/ruby/ext/grpc/rb_call.c
+++ b/src/ruby/ext/grpc/rb_call.c
@@ -235,8 +235,8 @@
 */
 static int grpc_rb_md_ary_fill_hash_cb(VALUE key, VALUE val, VALUE md_ary_obj) {
   grpc_metadata_array *md_ary = NULL;
-  int array_length;
-  int i;
+  long array_length;
+  long i;
 
   /* Construct a metadata object from key and value and add it */
   TypedData_Get_Struct(md_ary_obj, grpc_metadata_array,
diff --git a/src/ruby/ext/grpc/rb_channel.c b/src/ruby/ext/grpc/rb_channel.c
index 9bf1a9f..0cb6fa2 100644
--- a/src/ruby/ext/grpc/rb_channel.c
+++ b/src/ruby/ext/grpc/rb_channel.c
@@ -146,7 +146,7 @@
   target_chars = StringValueCStr(target);
   grpc_rb_hash_convert_to_channel_args(channel_args, &args);
   if (credentials == Qnil) {
-    ch = grpc_channel_create(target_chars, &args);
+    ch = grpc_insecure_channel_create(target_chars, &args);
   } else {
     creds = grpc_rb_get_wrapped_credentials(credentials);
     ch = grpc_secure_channel_create(creds, target_chars, &args);
diff --git a/src/ruby/ext/grpc/rb_grpc.c b/src/ruby/ext/grpc/rb_grpc.c
index 65d9c9a..327fd1a 100644
--- a/src/ruby/ext/grpc/rb_grpc.c
+++ b/src/ruby/ext/grpc/rb_grpc.c
@@ -139,7 +139,7 @@
           rb_raise(rb_eRangeError, "%f out of Time range",
                    RFLOAT_VALUE(time));
         }
-        t.tv_nsec = (time_t)(d * 1e9 + 0.5);
+        t.tv_nsec = (int)(d * 1e9 + 0.5);
       }
       break;
 
diff --git a/src/ruby/ext/grpc/rb_server_credentials.c b/src/ruby/ext/grpc/rb_server_credentials.c
index 5f40935..62c211d 100644
--- a/src/ruby/ext/grpc/rb_server_credentials.c
+++ b/src/ruby/ext/grpc/rb_server_credentials.c
@@ -176,11 +176,12 @@
   }
   key_cert_pair.private_key = RSTRING_PTR(pem_private_key);
   key_cert_pair.cert_chain = RSTRING_PTR(pem_cert_chain);
+  /* TODO Add a force_client_auth parameter and pass it here. */
   if (pem_root_certs == Qnil) {
-    creds = grpc_ssl_server_credentials_create(NULL, &key_cert_pair, 1);
+    creds = grpc_ssl_server_credentials_create(NULL, &key_cert_pair, 1, 0);
   } else {
     creds = grpc_ssl_server_credentials_create(RSTRING_PTR(pem_root_certs),
-                                               &key_cert_pair, 1);
+                                               &key_cert_pair, 1, 0);
   }
   if (creds == NULL) {
     rb_raise(rb_eRuntimeError, "could not create a credentials, not sure why");
diff --git a/templates/vsprojects/Grpc.mak.template b/templates/vsprojects/Grpc.mak.template
index 9d85376..9d2f676 100644
--- a/templates/vsprojects/Grpc.mak.template
+++ b/templates/vsprojects/Grpc.mak.template
@@ -33,16 +33,18 @@
 <%def name="to_windows_path(path)">${path.replace('/','\\')}</%def>\
 <%
   build_from_project_file = set(['gpr',
-                                 'grpc',
-                                 'grpc_unsecure',
                                  'gpr_test_util',
+                                 'grpc',
                                  'grpc_test_util',
                                  'grpc_test_util_unsecure',
+                                 'grpc_unsecure',
+                                 'grpc++',
+                                 'grpc++_unsecure'
                                 ])
   buildable_targets = [ target for target in targets + libs
                         if target.build in ['all', 'test', 'private', 'tool', 'benchmark'] and
                         target.language in ['c', 'c++'] and
-                        all([src.endswith('.c') for src in target.src]) and
+                        all([(src.endswith('.c') or src.endswith('.cc') or src.endswith('.proto')) for src in target.src]) and
                         'windows' in target.get('platforms', ['windows']) ]
   c_test_targets = [ target for target in buildable_targets if target.build == 'test' and not target.language == 'c++' ]
   cxx_test_targets = [ target for target in buildable_targets if target.build == 'test' and target.language == 'c++' ]
@@ -60,8 +62,19 @@
 OPENSSL_INCLUDES = .\packages\${get_openssl()}\build\native\include
 ZLIB_INCLUDES = .\packages\${get_zlib()}\build\native\include
 INCLUDES=/I$(REPO_ROOT) /I$(REPO_ROOT)\include /I$(OPENSSL_INCLUDES) /I$(ZLIB_INCLUDES)
-DEFINES=/D WIN32 /D _LIB /D _USE_32BIT_TIME_T /D _UNICODE /D UNICODE /D _CRT_SECURE_NO_WARNINGS
+
+GFLAGS_INCLUDES = .\..\third_party\gflags\include
+GTEST_INCLUDES = .\..\third_party\gtest\include
+PROTOBUF_INCLUDES = .\..\third_party\protobuf\src
+CXX_INCLUDES=/I$(GFLAGS_INCLUDES) /I$(GTEST_INCLUDES) /I$(PROTOBUF_INCLUDES)
+
+#_SCL_SECURE_NO_WARNINGS supresses a ton of "potentially unsafe use of std lib" warnings
+DEFINES=/D WIN32 /D _LIB /D _USE_32BIT_TIME_T /D _UNICODE /D UNICODE /D _CRT_SECURE_NO_WARNINGS /D _SCL_SECURE_NO_WARNINGS
+
+#important options: /TC vs. /TP: compile as C vs. compile as C++
 CFLAGS=/c $(INCLUDES) /Z7 /W3 /WX- /sdl $(DEFINES) /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /TC /analyze-
+CXXFLAGS=/c $(INCLUDES) $(CXX_INCLUDES) /Z7 /W3 /WX- /sdl $(DEFINES) /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Gd /TP /analyze-
+
 LFLAGS=/DEBUG /INCREMENTAL /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X86
 
 OPENSSL_LIBS=.\packages\${get_openssl()}\build\native\lib\v120\Win32\Debug\static\ssleay32.lib .\packages\${get_openssl()}\build\native\lib\v120\Win32\Debug\static\libeay32.lib
@@ -70,6 +83,12 @@
 ZLIB_LIBS=.\packages\${get_zlib()}\build\native\lib\v120\Win32\Debug\static\cdecl\zlib.lib
 LIBS=$(OPENSSL_LIBS) $(ZLIB_LIBS) $(GENERAL_LIBS) $(WINSOCK_LIBS)
 
+#shlwapi.lib provides PathMatchSpec() for gflags in windows
+GFLAGS_LIBS=.\..\third_party\gflags\lib\Debug\gflags.lib shlwapi.lib
+GTEST_LIBS=.\..\third_party\gtest\msvc\gtest\Debug\gtestd.lib
+PROTOBUF_LIBS=.\..\third_party\protobuf\vsprojects\Debug\libprotobuf.lib
+CXX_LIBS=$(GFLAGS_LIBS) $(GTEST_LIBS) $(PROTOBUF_LIBS)
+
 all: buildtests
 
 tools:
@@ -99,16 +118,33 @@
 ${target.name}.exe \
 % endfor
 
-	echo All tests built.
+	echo All C tests built.
 
 buildtests_cxx: \
 % for target in cxx_test_targets:
 ${target.name}.exe \
 % endfor
 
-	echo All tests built.
+	echo All C++ tests built.
 
 % for target in buildable_targets:
+
+## replace all .proto includes with .pb.cc / .grpc.pb.cc
+%if target.src:
+%for source in target.src:
+%if source.endswith(".proto"):
+<%
+      src_name_parts = source.split(".")
+      target.src.append(src_name_parts[0] + ".pb.cc")
+      target.src.append(src_name_parts[0] + ".grpc.pb.cc")
+%>\
+%endif
+%endfor
+%endif
+## remove all .proto includes
+<%
+  target.src = [item for item in target.src if not re.search('([^/]+)\.proto$', item)]
+%>\
 %if target.name in build_from_project_file:
 build_${target.name}:
 	msbuild grpc.sln /t:${target.name} /p:Configuration=Debug /p:Linkage-grpc_dependencies_zlib=static
@@ -116,11 +152,22 @@
 %if target.build == 'private':
 Debug\${target.name}.lib: \
 %else:
-${target.name}.exe: build_libs \
+${target.name}.exe: \
+%for dep in target.get('deps', []):
+%if dep in build_from_project_file:
+build_${dep} \
+%else:
+Debug\${dep}.lib \
+%endif
+%endfor
 %endif
 $(OUT_DIR)
 	echo Building ${target.name}
+%if target.language == 'c++':
+    $(CC) $(CXXFLAGS) /Fo:$(OUT_DIR)\ \
+%else:
 	$(CC) $(CFLAGS) /Fo:$(OUT_DIR)\ \
+%endif
 %for source in target.src:
 $(REPO_ROOT)\${to_windows_path(source)} \
 %endfor
@@ -135,13 +182,19 @@
 %for dep in target.get('deps', []):
 Debug\${dep}.lib \
 %endfor
+%if target.language == 'c++':
+$(CXX_LIBS) \
+%endif
 $(LIBS) \
 %endif
-%for source in target.src:
-$(OUT_DIR)\${re.search('([^/]+)\.c$', source).group(1)}.obj \
-%endfor
 %if not target.src:
 $(OUT_DIR)\dummy.obj \
+%else:
+%for source in target.src:
+%if re.search('([^/]+)\.c{1,2}$', source):
+$(OUT_DIR)\${re.search('([^/]+)\.c{1,2}$', source).group(1)}.obj \
+%endif
+%endfor
 %endif
 
 %if target.build != 'private':
diff --git a/templates/vsprojects/build_test_protos.sh b/templates/vsprojects/build_test_protos.sh
new file mode 100644
index 0000000..54edd36
--- /dev/null
+++ b/templates/vsprojects/build_test_protos.sh
@@ -0,0 +1,42 @@
+#!/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.
+
+GRPC_CPP_PLUGIN_PATH=`which grpc_cpp_plugin`
+
+cd `dirname $0`/../..
+
+find ./test -type f -name "*.proto" |
+while read p ; do
+  echo "processing $p"
+  DIR=$(dirname "$p")
+  protoc $p --grpc_out=./ --plugin=protoc-gen-grpc=$GRPC_CPP_PLUGIN_PATH
+  protoc $p --cpp_out=./
+done
diff --git a/templates/vsprojects/generate_debug_projects.sh b/templates/vsprojects/generate_debug_projects.sh
index 1bbe40b..f103ebe 100755
--- a/templates/vsprojects/generate_debug_projects.sh
+++ b/templates/vsprojects/generate_debug_projects.sh
@@ -37,26 +37,40 @@
 
 cd `dirname $0`/../..
 
-./tools/buildgen/generate_projects.sh
+git add .               #because we're using "git diff" to find changes to grpc.sln and then make files based on those changes, this prevents this file or other files from possibly being found in the diff
+
+./tools/buildgen/generate_projects-old.sh
+
+line_number=0
 
 git diff |
-grep \\+Project |
-cut -d\" -f 4 |
-sort -u |
-grep _test$ |
+grep -A2 \\+Project |       #find "Project" immediately after a backslash (escaped), plus 2 additional lines to capture the "libs = ", plus 1 line of "--".  matches will come from the generated grpc.sln
 while read p ; do
-  mkdir -p templates/vsprojects/$p
-  echo '<%namespace file="../vcxproj_defs.include" import="gen_project"/>${gen_project("'$p'", targets)}' > templates/vsprojects/$p/$p.vcxproj.template
+  line_number=$((line_number + 1))
+  if [ "$line_number" -gt "4" ]; then
+    line_number=1;
+  fi
+  echo $line_number
+  echo $p
+  if [ "$line_number" -eq "1" ]; then
+    project_name=$(echo "$p" | cut -d\" -f 4)          #sed: extract line N only; cut with delimiter: ".  select only field 4
+  fi
+  if [ "$line_number" -eq "3" ]; then
+    lib_setting=$(echo "$p" | cut -d\" -f 2)          #
+    echo "project_name"
+    echo $project_name
+    echo "lib_setting"
+    echo $lib_setting
+    mkdir -p templates/vsprojects/$project_name
+    if [ "$lib_setting" = "True" ]; then
+      echo "lib: true"
+      echo '<%namespace file="../vcxproj_defs.include" import="gen_project"/>${gen_project("'$project_name'", libs)}' > templates/vsprojects/$project_name/$project_name.vcxproj.template
+    else
+      echo "lib: not true"
+      echo '<%namespace file="../vcxproj_defs.include" import="gen_project"/>${gen_project("'$project_name'", targets)}' > templates/vsprojects/$project_name/$project_name.vcxproj.template
+    fi
+  fi
+ # sleep .5     #for testing
 done
 
-git diff |
-grep \\+Project |
-cut -d\" -f 4 |
-sort -u |
-grep -v _test$ |
-while read p ; do
-  mkdir -p templates/vsprojects/$p
-  echo '<%namespace file="../vcxproj_defs.include" import="gen_project"/>${gen_project("'$p'", libs)}' > templates/vsprojects/$p/$p.vcxproj.template
-done
-
-./tools/buildgen/generate_projects.sh
+./tools/buildgen/generate_projects-old.sh
diff --git a/templates/vsprojects/sln_defs.include b/templates/vsprojects/sln_defs.include
index ee05d0f..4ba0fbf 100644
--- a/templates/vsprojects/sln_defs.include
+++ b/templates/vsprojects/sln_defs.include
@@ -15,6 +15,13 @@
 %>\
 % for project in solution_projects:
 Project("${cpp_proj_type}") = "${project.name}", "${project.name}\${project.name}.vcxproj", "${project.vs_project_guid}"
+	ProjectSection(myProperties) = preProject
+  % if project.is_library:
+        	lib = "True"
+  % else:
+        	lib = "False"
+  % endif
+	EndProjectSection
   % if project.get('deps', None):
 	ProjectSection(ProjectDependencies) = postProject
     % for dep in project.get('deps', []):
@@ -47,4 +54,4 @@
 		HideSolutionNode = FALSE
 	EndGlobalSection
 EndGlobal
-</%def>\
\ No newline at end of file
+</%def>\
diff --git a/templates/vsprojects/vcxproj_defs.include b/templates/vsprojects/vcxproj_defs.include
index 55ec373..39c7386 100644
--- a/templates/vsprojects/vcxproj_defs.include
+++ b/templates/vsprojects/vcxproj_defs.include
@@ -12,19 +12,21 @@
     if t.name == name:
       target = t
   if not configuration_type and target:
+    print target.name
     if target.build == 'test' or target.build == 'tool':
       configuration_type = 'Application'
   if not configuration_type:
     configuration_type = 'StaticLibrary'
   if not project_guid:
     project_guid = project.vs_project_guid
+  if target.build == 'test' and target.language == 'c++':
+    props.extend(['cpptest'])
   if configuration_type == 'Application':
+    print target.build
     if target.build == 'protoc':
       props.extend(['protoc'])
     else:
       props.extend(['winsock', 'protobuf', 'zlib', 'openssl'])
-    if target.language == 'c++':
-      props.extend(['protobuf'])
   props.extend(['global'])
 %>\
 <?xml version="1.0" encoding="utf-8"?>
@@ -113,6 +115,13 @@
   <PropertyGroup Label="UserMacros" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <TargetName>${name}</TargetName>
+    % if "zlib" in packages:
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    % endif
+    % if "openssl" in packages:
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+    % endif
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
     <TargetName>${name}</TargetName>
@@ -200,8 +209,20 @@
   % if project.get('src',[]):
   <ItemGroup>
     % for src_name in project.src:
+      % if src_name.endswith(".proto"):
+<% src_name_parts = src_name.split(".") %>\
+    <ClCompile Include="${get_repo_root()}\${to_windows_path(src_name_parts[0] + ".pb.cc")}">
+    </ClCompile>
+    <ClInclude Include="${get_repo_root()}\${to_windows_path(src_name_parts[0] + ".pb.h")}">
+    </ClInclude>
+    <ClCompile Include="${get_repo_root()}\${to_windows_path(src_name_parts[0] + ".grpc.pb.cc")}">
+    </ClCompile>
+    <ClInclude Include="${get_repo_root()}\${to_windows_path(src_name_parts[0] + ".grpc.pb.h")}">
+    </ClInclude>
+      % else:
     <ClCompile Include="${get_repo_root()}\${to_windows_path(src_name)}">
     </ClCompile>
+      % endif
     % endfor
   </ItemGroup>
   % elif configuration_type != 'StaticLibrary':
@@ -230,4 +251,4 @@
   </ImportGroup>
 ${gen_package_ensure(packages)}\
 </Project>
-</%def>\
\ No newline at end of file
+</%def>\
diff --git a/test/core/end2end/dualstack_socket_test.c b/test/core/end2end/dualstack_socket_test.c
index 453376c..77bea2a 100644
--- a/test/core/end2end/dualstack_socket_test.c
+++ b/test/core/end2end/dualstack_socket_test.c
@@ -113,7 +113,7 @@
   } else {
     gpr_join_host_port(&client_hostport, client_host, port);
   }
-  client = grpc_channel_create(client_hostport, NULL);
+  client = grpc_insecure_channel_create(client_hostport, NULL);
 
   gpr_log(GPR_INFO, "Testing with server=%s client=%s (expecting %s)",
           server_hostport, client_hostport, expect_ok ? "success" : "failure");
diff --git a/test/core/end2end/fixtures/chttp2_fullstack.c b/test/core/end2end/fixtures/chttp2_fullstack.c
index 8a1530e..6647b94 100644
--- a/test/core/end2end/fixtures/chttp2_fullstack.c
+++ b/test/core/end2end/fixtures/chttp2_fullstack.c
@@ -72,7 +72,7 @@
 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_channel_create(ffd->localaddr, client_args);
+  f->client = grpc_insecure_channel_create(ffd->localaddr, client_args);
   GPR_ASSERT(f->client);
 }
 
diff --git a/test/core/end2end/fixtures/chttp2_fullstack_compression.c b/test/core/end2end/fixtures/chttp2_fullstack_compression.c
index 0a9a312..f3d1fa2 100644
--- a/test/core/end2end/fixtures/chttp2_fullstack_compression.c
+++ b/test/core/end2end/fixtures/chttp2_fullstack_compression.c
@@ -82,7 +82,8 @@
   }
   ffd->client_args_compression = grpc_channel_args_set_compression_algorithm(
       client_args, GRPC_COMPRESS_GZIP);
-  f->client = grpc_channel_create(ffd->localaddr, ffd->client_args_compression);
+  f->client = grpc_insecure_channel_create(ffd->localaddr,
+                                           ffd->client_args_compression);
 }
 
 void chttp2_init_server_fullstack_compression(grpc_end2end_test_fixture *f,
diff --git a/test/core/end2end/fixtures/chttp2_fullstack_uds_posix.c b/test/core/end2end/fixtures/chttp2_fullstack_uds_posix.c
index 351e1c5..89ad7b8 100644
--- a/test/core/end2end/fixtures/chttp2_fullstack_uds_posix.c
+++ b/test/core/end2end/fixtures/chttp2_fullstack_uds_posix.c
@@ -78,7 +78,7 @@
 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_channel_create(ffd->localaddr, client_args);
+  f->client = grpc_insecure_channel_create(ffd->localaddr, client_args);
 }
 
 void chttp2_init_server_fullstack(grpc_end2end_test_fixture *f,
diff --git a/test/core/end2end/fixtures/chttp2_fullstack_uds_posix_with_poll.c b/test/core/end2end/fixtures/chttp2_fullstack_uds_posix_with_poll.c
index 03d3be5..a2ab25d 100644
--- a/test/core/end2end/fixtures/chttp2_fullstack_uds_posix_with_poll.c
+++ b/test/core/end2end/fixtures/chttp2_fullstack_uds_posix_with_poll.c
@@ -78,7 +78,7 @@
 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_channel_create(ffd->localaddr, client_args);
+  f->client = grpc_insecure_channel_create(ffd->localaddr, client_args);
 }
 
 void chttp2_init_server_fullstack(grpc_end2end_test_fixture *f,
diff --git a/test/core/end2end/fixtures/chttp2_fullstack_with_poll.c b/test/core/end2end/fixtures/chttp2_fullstack_with_poll.c
index 69860d0..93786d0 100644
--- a/test/core/end2end/fixtures/chttp2_fullstack_with_poll.c
+++ b/test/core/end2end/fixtures/chttp2_fullstack_with_poll.c
@@ -72,7 +72,7 @@
 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_channel_create(ffd->localaddr, client_args);
+  f->client = grpc_insecure_channel_create(ffd->localaddr, client_args);
 }
 
 void chttp2_init_server_fullstack(grpc_end2end_test_fixture *f,
diff --git a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c
index 73a3611..6d5669d 100644
--- a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c
+++ b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c
@@ -115,7 +115,7 @@
   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);
+      grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0);
   chttp2_init_server_secure_fullstack(f, server_args, ssl_creds);
 }
 
diff --git a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_poll.c b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_poll.c
index b1ac3e5..d0cc3dd 100644
--- a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_poll.c
+++ b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_poll.c
@@ -115,7 +115,7 @@
   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);
+      grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0);
   chttp2_init_server_secure_fullstack(f, server_args, ssl_creds);
 }
 
diff --git a/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c b/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c
index de418bf..f74ed93 100644
--- a/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c
+++ b/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c
@@ -120,7 +120,7 @@
   grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {test_server1_key,
                                                   test_server1_cert};
   grpc_server_credentials *ssl_creds =
-      grpc_ssl_server_credentials_create(NULL, &pem_key_cert_pair, 1);
+      grpc_ssl_server_credentials_create(NULL, &pem_key_cert_pair, 1, 0);
   chttp2_init_server_secure_fullstack(f, server_args, ssl_creds);
 }
 
diff --git a/test/core/end2end/no_server_test.c b/test/core/end2end/no_server_test.c
index 79797f9..6f1133c 100644
--- a/test/core/end2end/no_server_test.c
+++ b/test/core/end2end/no_server_test.c
@@ -61,7 +61,7 @@
   cqv = cq_verifier_create(cq);
 
   /* create a call, channel to a non existant server */
-  chan = grpc_channel_create("nonexistant:54321", NULL);
+  chan = grpc_insecure_channel_create("nonexistant:54321", NULL);
   call = grpc_channel_create_call(chan, cq, "/Foo", "nonexistant", deadline);
 
   op = ops;
diff --git a/test/core/end2end/tests/request_response_with_metadata_and_payload.c b/test/core/end2end/tests/request_response_with_metadata_and_payload.c
index ef6dfe9..9821d78 100644
--- a/test/core/end2end/tests/request_response_with_metadata_and_payload.c
+++ b/test/core/end2end/tests/request_response_with_metadata_and_payload.c
@@ -111,8 +111,8 @@
   gpr_timespec deadline = five_seconds_time();
   grpc_metadata meta_c[2] = {{"key1", "val1", 4, {{NULL, NULL, NULL}}},
                              {"key2", "val2", 4, {{NULL, NULL, NULL}}}};
-  grpc_metadata meta_s[2] = {{"key3", "val3", 4, {{NULL, NULL, NULL}}},
-                             {"key4", "val4", 4, {{NULL, NULL, NULL}}}};
+  grpc_metadata meta_s[2] = {{"KeY3", "val3", 4, {{NULL, NULL, NULL}}},
+                             {"KeY4", "val4", 4, {{NULL, NULL, NULL}}}};
   grpc_end2end_test_fixture f = begin_test(
       config, "test_request_response_with_metadata_and_payload", NULL, NULL);
   cq_verifier *cqv = cq_verifier_create(f.cq);
diff --git a/test/core/fling/client.c b/test/core/fling/client.c
index 2b19654..5647a16 100644
--- a/test/core/fling/client.c
+++ b/test/core/fling/client.c
@@ -183,7 +183,7 @@
     return 1;
   }
 
-  channel = grpc_channel_create(target, NULL);
+  channel = grpc_insecure_channel_create(target, NULL);
   cq = grpc_completion_queue_create();
   the_buffer = grpc_raw_byte_buffer_create(&slice, payload_size);
   histogram = gpr_histogram_create(0.01, 60e9);
diff --git a/test/core/fling/server.c b/test/core/fling/server.c
index 082bbd3..8f34904 100644
--- a/test/core/fling/server.c
+++ b/test/core/fling/server.c
@@ -210,7 +210,7 @@
     grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {test_server1_key,
                                                     test_server1_cert};
     grpc_server_credentials *ssl_creds =
-        grpc_ssl_server_credentials_create(NULL, &pem_key_cert_pair, 1);
+        grpc_ssl_server_credentials_create(NULL, &pem_key_cert_pair, 1, 0);
     server = grpc_server_create(NULL);
     GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr, ssl_creds));
     grpc_server_credentials_release(ssl_creds);
diff --git a/test/core/transport/metadata_test.c b/test/core/transport/metadata_test.c
index a932e04..4a4d4bc 100644
--- a/test/core/transport/metadata_test.c
+++ b/test/core/transport/metadata_test.c
@@ -63,9 +63,9 @@
   LOG_TEST("test_create_string");
 
   ctx = grpc_mdctx_create();
-  s1 = grpc_mdstr_from_string(ctx, "hello");
-  s2 = grpc_mdstr_from_string(ctx, "hello");
-  s3 = grpc_mdstr_from_string(ctx, "very much not hello");
+  s1 = grpc_mdstr_from_string(ctx, "hello", 0);
+  s2 = grpc_mdstr_from_string(ctx, "hello", 0);
+  s3 = grpc_mdstr_from_string(ctx, "very much not hello", 0);
   GPR_ASSERT(s1 == s2);
   GPR_ASSERT(s3 != s1);
   GPR_ASSERT(gpr_slice_str_cmp(s1->slice, "hello") == 0);
@@ -190,7 +190,7 @@
 
   for (i = 0; i < nstrs; i++) {
     gpr_asprintf(&buffer, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%dx", i);
-    strs[i] = grpc_mdstr_from_string(ctx, buffer);
+    strs[i] = grpc_mdstr_from_string(ctx, buffer, 0);
     shuf[i] = i;
     gpr_free(buffer);
   }
@@ -212,7 +212,7 @@
     GRPC_MDSTR_UNREF(strs[shuf[i]]);
     for (j = i + 1; j < nstrs; j++) {
       gpr_asprintf(&buffer, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%dx", shuf[j]);
-      test = grpc_mdstr_from_string(ctx, buffer);
+      test = grpc_mdstr_from_string(ctx, buffer, 0);
       GPR_ASSERT(test == strs[shuf[j]]);
       GRPC_MDSTR_UNREF(test);
       gpr_free(buffer);
@@ -235,13 +235,13 @@
   ctx = grpc_mdctx_create();
 
   str = grpc_mdstr_from_string(
-      ctx, "123456789012345678901234567890123456789012345678901234567890");
+      ctx, "123456789012345678901234567890123456789012345678901234567890", 0);
   slice = gpr_slice_ref(str->slice);
   GRPC_MDSTR_UNREF(str);
   gpr_slice_unref(slice);
 
   str = grpc_mdstr_from_string(
-      ctx, "123456789012345678901234567890123456789012345678901234567890");
+      ctx, "123456789012345678901234567890123456789012345678901234567890", 0);
   slice = gpr_slice_ref(str->slice);
   gpr_slice_unref(slice);
   GRPC_MDSTR_UNREF(str);
@@ -258,7 +258,7 @@
   LOG_TEST("test_base64_and_huffman_works");
 
   ctx = grpc_mdctx_create();
-  str = grpc_mdstr_from_string(ctx, "abcdefg");
+  str = grpc_mdstr_from_string(ctx, "abcdefg", 0);
   slice1 = grpc_mdstr_as_base64_encoded_and_huffman_compressed(str);
   slice2 = grpc_chttp2_base64_encode_and_huffman_compress(str->slice);
   GPR_ASSERT(0 == gpr_slice_cmp(slice1, slice2));
diff --git a/tools/buildgen/generate_projects-old.sh b/tools/buildgen/generate_projects-old.sh
new file mode 100644
index 0000000..5399867
--- /dev/null
+++ b/tools/buildgen/generate_projects-old.sh
@@ -0,0 +1,76 @@
+#!/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.
+
+
+set -e
+
+if [ "x$TEST" = "x" ] ; then
+  TEST=false
+fi
+
+
+cd `dirname $0`/../..
+mako_renderer=tools/buildgen/mako_renderer.py
+
+if [ "x$TEST" != "x" ] ; then
+  tools/buildgen/build-cleaner.py build.json
+fi
+
+. tools/buildgen/generate_build_additions.sh
+
+global_plugins=`find ./tools/buildgen/plugins -name '*.py' |
+  sort | grep -v __init__ | awk ' { printf "-p %s ", $0 } '`
+
+for dir in . ; do
+  local_plugins=`find $dir/templates -name '*.py' |
+    sort | grep -v __init__ | awk ' { printf "-p %s ", $0 } '`
+
+  plugins="$global_plugins $local_plugins"
+
+  find -L $dir/templates -type f -and -name *.template | while read file ; do
+    out=${dir}/${file#$dir/templates/}  # strip templates dir prefix
+    out=${out%.*}  # strip template extension
+    echo "generating file: $out"
+    json_files="build.json $gen_build_files"
+    data=`for i in $json_files ; do echo $i ; done | awk ' { printf "-d %s ", $0 } '`
+    if [ "x$TEST" = "xtrue" ] ; then
+      actual_out=$out
+      out=`mktemp /tmp/gentXXXXXX`
+    fi
+    mkdir -p `dirname $out`  # make sure dest directory exist
+    $mako_renderer $plugins $data -o $out $file
+    if [ "x$TEST" = "xtrue" ] ; then
+      diff -q $out $actual_out
+      rm $out
+    fi
+  done
+done
+
+rm $gen_build_files
diff --git a/tools/buildgen/plugins/generate_vsprojects.py b/tools/buildgen/plugins/generate_vsprojects.py
index 150e72e..413056f 100755
--- a/tools/buildgen/plugins/generate_vsprojects.py
+++ b/tools/buildgen/plugins/generate_vsprojects.py
@@ -70,7 +70,7 @@
                 if project.get('vs_project_guid', None)]
 
   projects = [project for project in projects
-                if project['language'] != 'c++' or project['build'] == 'all' or project['build'] == 'protoc']
+                if project['language'] != 'c++' or project['build'] == 'all' or project['build'] == 'protoc' or (project['language'] == 'c++' and  (project['build'] == 'test' or project['build'] == 'private'))]
 
   project_dict = dict([(p['name'], p) for p in projects])
 
diff --git a/tools/gce_setup/cloud_prod_runner.sh b/tools/gce_setup/cloud_prod_runner.sh
index 4206a66..7343702 100755
--- a/tools/gce_setup/cloud_prod_runner.sh
+++ b/tools/gce_setup/cloud_prod_runner.sh
@@ -34,8 +34,8 @@
 
 main() {
   source grpc_docker.sh
-  test_cases=(large_unary empty_unary ping_pong client_streaming server_streaming cancel_after_begin cancel_after_first_response)
-  auth_test_cases=(service_account_creds compute_engine_creds jwt_token_creds)
+  test_cases=(large_unary empty_unary ping_pong client_streaming server_streaming cancel_after_begin cancel_after_first_response empty_stream timeout_on_sleeping_server)
+  auth_test_cases=(service_account_creds compute_engine_creds jwt_token_creds oauth2_auth_token per_rpc_creds)
   clients=(cxx java go ruby node csharp_mono csharp_dotnet python php)
   for test_case in "${test_cases[@]}"
   do
diff --git a/tools/gce_setup/grpc_docker.sh b/tools/gce_setup/grpc_docker.sh
index b53aa98..c06780a 100755
--- a/tools/gce_setup/grpc_docker.sh
+++ b/tools/gce_setup/grpc_docker.sh
@@ -508,7 +508,12 @@
   grpc_gen_test_cmd="grpc_cloud_prod_auth_"
   [[ -n $1 ]] && {  # test_case
     test_case=$1
-    grpc_gen_test_cmd+="$1"
+    test_command="service_account_creds"
+    if [ "$test_case" == "compute_engine_creds" ]
+    then
+      test_command="compute_engine_creds"
+    fi
+    grpc_gen_test_cmd+=$test_command
     shift
   } || {
     echo "$FUNCNAME: missing arg: test_case" 1>&2
diff --git a/tools/gce_setup/interop_test_runner.sh b/tools/gce_setup/interop_test_runner.sh
index 6ff3731..5064714 100755
--- a/tools/gce_setup/interop_test_runner.sh
+++ b/tools/gce_setup/interop_test_runner.sh
@@ -37,7 +37,7 @@
 
 main() {
   source grpc_docker.sh
-  test_cases=(large_unary empty_unary ping_pong client_streaming server_streaming cancel_after_begin cancel_after_first_response)
+  test_cases=(large_unary empty_unary ping_pong client_streaming server_streaming cancel_after_begin cancel_after_first_response empty_stream timeout_on_sleeping_server)
   clients=(cxx java go ruby node python csharp_mono php)
   servers=(cxx java go ruby node python csharp_mono)
   for test_case in "${test_cases[@]}"
diff --git a/tools/jenkins/run_jenkins.sh b/tools/jenkins/run_jenkins.sh
index 56f9e82..93cf82d 100755
--- a/tools/jenkins/run_jenkins.sh
+++ b/tools/jenkins/run_jenkins.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
 # Copyright 2015, Google Inc.
 # All rights reserved.
 #
@@ -31,6 +31,8 @@
 # This script is invoked by Jenkins and triggers a test run based on
 # env variable settings.
 #
+# Bootstrap into bash
+[ -z $1 ] && exec bash $0 bootstrapped
 # Setting up rvm environment BEFORE we set -ex.
 [[ -s /etc/profile.d/rvm.sh ]] && . /etc/profile.d/rvm.sh
 # To prevent cygwin bash complaining about empty lines ending with \r
@@ -90,7 +92,9 @@
   docker cp $DOCKER_CID:/var/local/git/grpc/report.xml $git_root
   sleep 4
   docker rm $DOCKER_CID || true
-
+elif [ "$platform" == "interop" ]
+then
+  python tools/run_tests/run_interops.py --language=$language
 elif [ "$platform" == "windows" ]
 then
   echo "building $language on Windows"
@@ -103,11 +107,18 @@
   /cygdrive/c/nuget/nuget.exe restore src/csharp/Grpc.sln
 
   python tools/run_tests/run_tests.py -t -l $language -x report.xml || true
+
 elif [ "$platform" == "macos" ]
 then
   echo "building $language on MacOS"
 
   ./tools/run_tests/run_tests.py -t -l $language -c $config -x report.xml || true
+
+elif [ "$platform" == "freebsd" ]
+then
+  echo "building $language on FreeBSD"
+
+  MAKE=gmake ./tools/run_tests/run_tests.py -t -l $language -c $config -x report.xml || true
 else
   echo "Unknown platform $platform"
   exit 1
diff --git a/tools/run_tests/jobset.py b/tools/run_tests/jobset.py
index 46137f0..ec25b47 100755
--- a/tools/run_tests/jobset.py
+++ b/tools/run_tests/jobset.py
@@ -206,7 +206,7 @@
                 do_newline=self._newline_on_success or self._travis)
         if self._bin_hash:
           update_cache.finished(self._spec.identity(), self._bin_hash)
-    elif self._state == _RUNNING and time.time() - self._start > 600:
+    elif self._state == _RUNNING and time.time() - self._start > 900:
       self._tempfile.seek(0)
       stdout = self._tempfile.read()
       filtered_stdout = filter(lambda x: x in string.printable, stdout.decode(errors='ignore'))
diff --git a/tools/run_tests/run_interops.py b/tools/run_tests/run_interops.py
new file mode 100755
index 0000000..1cf2685
--- /dev/null
+++ b/tools/run_tests/run_interops.py
@@ -0,0 +1,36 @@
+import argparse
+import xml.etree.cElementTree as ET
+import jobset
+
+argp = argparse.ArgumentParser(description='Run interop tests.')
+argp.add_argument('-l', '--language',
+                  choices=['build_only', 'c++'],
+                  nargs='+',
+                  default=['build_only'])
+args = argp.parse_args()
+
+# build job
+build_steps = 'tools/run_tests/run_interops_build.sh'
+build_job = jobset.JobSpec(cmdline=build_steps, shortname='build')
+
+# test jobs
+_TESTS = ['large_unary', 'empty_unary', 'ping_pong', 'client_streaming', 'server_streaming']
+jobs = []
+jobNumber = 0
+for lang in args.language:
+  for test in _TESTS:
+    test_job = jobset.JobSpec(cmdline=['tools/run_tests/run_interops_test.sh', '%s' % lang, '%s' % test], shortname=test)
+    jobs.append(test_job)
+    jobNumber+=1
+
+root = ET.Element('testsuites')
+testsuite = ET.SubElement(root, 'testsuite', id='1', package='grpc', name='tests')
+
+# always do the build of docker first, and then all the tests can run in parallel
+jobset.run([build_job], maxjobs=1, xml_report=testsuite)
+jobset.run(jobs, maxjobs=jobNumber, xml_report=testsuite)
+
+tree = ET.ElementTree(root)
+tree.write('report.xml', encoding='UTF-8')
+
+
diff --git a/tools/run_tests/run_interops_build.sh b/tools/run_tests/run_interops_build.sh
new file mode 100755
index 0000000..23441a5
--- /dev/null
+++ b/tools/run_tests/run_interops_build.sh
@@ -0,0 +1,47 @@
+#!/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.
+
+set -e
+
+#clean up any old docker files and start mirroring repository if not started already
+sudo docker rmi -f grpc/cxx || true
+sudo docker rmi -f grpc/base || true
+sudo docker rmi -f 0.0.0.0:5000/grpc/base || true
+sudo docker run -d -e GCS_BUCKET=docker-interop-images  -e STORAGE_PATH=/admin/docker_images -p 5000:5000 google/docker-registry || true
+
+#prepare building by pulling down base images and necessary files
+sudo docker pull 0.0.0.0:5000/grpc/base
+sudo docker tag -f 0.0.0.0:5000/grpc/base grpc/base
+gsutil cp -R gs://docker-interop-images/admin/service_account tools/dockerfile/grpc_cxx
+gsutil cp -R gs://docker-interop-images/admin/cacerts tools/dockerfile/grpc_cxx
+
+#build docker file, add more languages later
+sudo docker build --no-cache -t grpc/cxx tools/dockerfile/grpc_cxx
diff --git a/tools/run_tests/run_interops_test.sh b/tools/run_tests/run_interops_test.sh
new file mode 100755
index 0000000..1d0eeda
--- /dev/null
+++ b/tools/run_tests/run_interops_test.sh
@@ -0,0 +1,43 @@
+#!/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.
+
+language=$1
+test_case=$2
+
+set -e
+if [ "$language" = "c++" ]
+then
+  sudo docker run grpc/cxx /var/local/git/grpc/bins/opt/interop_client --enable_ssl --use_prod_roots --server_host_override=grpc-test.sandbox.google.com --server_host=grpc-test.sandbox.google.com --server_port=443 --test_case=$test_case
+else
+  echo "interop testss not added for $language"
+  exit 1
+fi
+
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index 77cc02a..28980c1 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -458,7 +458,7 @@
                           cwd='vsprojects', shell=True)
 else:
   def make_jobspec(cfg, targets):
-    return jobset.JobSpec(['make',
+    return jobset.JobSpec([os.getenv('MAKE', 'make'),
                            '-j', '%d' % (multiprocessing.cpu_count() + 1),
                            'EXTRA_DEFINES=GRPC_TEST_SLOWDOWN_MACHINE_FACTOR=%f' %
                                args.slowdown,
diff --git a/vsprojects/README.md b/vsprojects/README.md
index dade9e5..e6cbf83 100644
--- a/vsprojects/README.md
+++ b/vsprojects/README.md
@@ -19,19 +19,62 @@
 1. open `grpc.sln` with Visual Studio and hit "Build".
 2. build from commandline using `msbuild grpc.sln /p:Configuration=Debug`
 
-#Testing
+#C/C++ Test Dependencies
+   * gtest isn't available as a git repo like the other dependencies.  download it and add it to `/third_party/gtest/` (the folder will end up with `/build-aux/`, `/cmake/`, `/codegear/`, etc. folders in it).  
+    * if using vs2013: open/import the gtest solution in `/msvc/`, and save over the first solution (you will have to change it from read-only).  change all projects to use `/MDd` (Property Pages - C/C++ - Code Generation - Runtime Library) and build. This is a "multithreaded debug" setting and it needs to match grpc.
+    * build all
+   * open protobuf solution in `/third_party/protobuf/vsprojects`
+    * if using vs2013: on import the gtest stuff will probably fail, I think the paths are interpreted wrong.  it's ok.
+    * tests and test_plugin will fail when built.  also ok
+    * build all
+   *  gflags is automatically imported as a git submodule but it needs to have CMake run on it to be ready for a specific platform
+    * download [CMake](http://www.cmake.org/) windows installer; install
+    * open visual studio developer command prompt (not sure if dev command prompt is necessary)
+    * run `cmake <path to gtest directory>`
+    * this will build a `.sln` and fill up the `/third_party/gflags/include/gflags/` directory with headers
+    * build all
+   * install [NuGet](http://www.nuget.org)
+    * nuget should automatically bring in built versions of zlib and openssl when building grpc.sln (the versions in `/third_party/` are not used).  If it doesn't work use `tools->nuget...->manage...`.  The packages are put in `/vsprojects/packages/`
 
-Use `run_tests.py`, that also supports Windows (with a bit limited experience).
-```
-> REM Run from repository root.
-> python tools\run_tests\run_tests.py -l c
-```
+#C/C++ Test Solution/Project Build Steps
+   * A basic git version of grpc only has templates for non-test items.  This checklist adds test items to grpc.sln and makes individual vs projects for them
+   * set up dependencies (above)
+   * add `"debug": true,` to the top of build.json.  This is the base file for all build tracking, see [templates](https://github.com/grpc/grpc/tree/master/templates) for more information
+    * `"debug": true,` gets picked up by `/tools/buildgen/plugins/generate_vsprojects.py`.  It tells the script to add visual studio GUIDs to all projects.  Otherwise only the projects that already have GUIDs in build.json will be built
+   * run `/templates/vsprojects/generate_debug_projects.sh` to make debug templates/projects.  This runs a regular visual studio buildgen process, which creates the `.sln` file with all of the new debug projects, then uses git diff to find the new project names from the `.sln` that need templates added.  It builds the new templates based on the diff, then re-runs the visual studio buildgen, which builds the vs projects for each of the new debug targets
+    * copy over the `/vsprojects/` folder to your windows build setup (assuming this was built on linux in order to have easy access to python/mako and shell scripts)
+   * run `/templates/vsprojects/build_test_protos.sh`
+    * this builds all `.proto` files in `/test/` in-place.  there might be a better place to put them that mirrors what happens in the linux build process (todo)
+    * each `.proto` file gets built into a `.grpc.pb.cc`, .`grpc.pb.h`, `.pb.cc`, and `.pb.h`.  These are included in each test project in lieu of the `.proto` includes specified in `build.json`.  This substitution is done by `/templates/vsprojects/vcxproj_defs.include`
+    * copy over the `/test/` folder in order to get the new files (assuming this was built on linux in order to have an easy protobuf+grpc plugin installation)
 
-Also, you can `make.bat` directly to build and run gRPC tests.
-```
-> REM Run from this directory.
-> make.bat alarm_test
-```
+#Making and running tests with `/tools/run_tests/run_tests.py` or `/vsprojects/make.bat`
+`run_tests.py` and `make.bat` both rely on `/vsprojects/grpc.mak`, an NMAKE script that includes C/C++ tests in addition to the base grpc projects.  It builds the base projects by calling grpc.sln, but most things are built with a command line similar to a makefile workflow.
+
+ arguments for `/vsprojects/make.bat`:
+
+ * no options or `all` or `buildtests`: builds all tests
+ * `buildtests_c`: just c tests
+ * `buildtests_cxx`: just c++ tests
+ * names of individual tests: just those tests (example: `make.bat gpr_string_test`)
+
+using `run_tests.py` on windows:
+
+ * when `run_tests.py` detects that it's running on windows it calls `make.bat` to build the tests and expects to find tests in `/vsprojects/test_bins/`
+
+`run_tests.py` options:
+
+ * `run_tests.py --help`
+ * `run_tests.py -l c`: run c language tests
+ * `run_tests.py -l c++`: run c++ language tests
+ * note: `run_tests.py` doesn't normally show build steps, so if a build fails it is best to fall back to `make.bat`
+ * if `make.bat` fails, it might be easier to open up the `.sln` file in the visual studio gui (see above for how to build the test projects) and build the offending test from its project file.  The `.mak` and project file templates are slightly different, so it's possible that a project will build one way and not another.  Please report this if it happens.
+
+It can be helpful to disable the firewall when running tests so that 400 connection warnings don't pop up.
+
+Individual tests can be run by directly running the executable in `/vsprojects/run_tests/` (this is `/bins/opt/` on linux).  Many C tests have no output; they either pass or fail internally and communicate this with their exit code (`0=pass`, `nonzero=fail`)
+
+`run_tests.py` will fail if it can't build something, so not-building tests are disabled with a "platforms = posix" note in build.json.  The buildgen tools will not add a test to a windows build unless it is marked "windows" or has no platforms identified.  As tests are ported they will get this mark removed.
 
 # Building protoc plugins
 For generating service stub code, gRPC relies on plugins for `protoc` (the protocol buffer compiler). The solution `grpc_protoc_plugins.sln` allows you to build
diff --git a/vsprojects/cpptest.props b/vsprojects/cpptest.props
new file mode 100644
index 0000000..c5ffd54
--- /dev/null
+++ b/vsprojects/cpptest.props
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ImportGroup Label="PropertySheets" />
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup />
+  <ItemDefinitionGroup>
+    <ClCompile>
+      <AdditionalIncludeDirectories>$(ProjectDir)\..\..;$(ProjectDir)\..\..\include;$(ProjectDir)\..\..\third_party\protobuf\src;$(ProjectDir)\..\..\third_party\gtest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <WarningLevel>EnableAllWarnings</WarningLevel>
+    </ClCompile>
+    <Link>
+      <AdditionalDependencies>grpc++_test_util.lib;grpc_test_util.lib;gpr_test_util.lib;gtestd.lib;gflags.lib;shlwapi.lib;gpr.lib;grpc.lib;grpc++.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalLibraryDirectories>$(ProjectDir)\..\..\third_party\gtest\msvc\gtest\Debug;$(ProjectDir)\..\..\third_party\gflags\lib\Debug;$(ProjectDir)\..\Debug;$(ProjectDir)\..\packages\grpc.dependencies.openssl.1.0.2.2\build\native\lib\$(PlatformToolset)\$(Platform)\$(Configuration)\static;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup />
+</Project>
diff --git a/vsprojects/global.props b/vsprojects/global.props
index 14acf46..6858bd7 100644
--- a/vsprojects/global.props
+++ b/vsprojects/global.props
@@ -5,10 +5,10 @@
   <PropertyGroup />
   <ItemDefinitionGroup>
     <ClCompile>
-      <AdditionalIncludeDirectories>$(ProjectDir)\..\..;$(ProjectDir)\..\..\include;$(ProjectDir)\..\..\third_party\protobuf\src;$(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(ProjectDir)\..\..;$(ProjectDir)\..\..\include;$(ProjectDir)\..\..\third_party\protobuf\src;$(ProjectDir)\..\packages\grpc.dependencies.openssl.1.0.2.2\build\native\include;$(ProjectDir)\..\..\third_party\gflags\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <WarningLevel>EnableAllWarnings</WarningLevel>
     </ClCompile>
   </ItemDefinitionGroup>
   <ItemGroup />
-</Project>
\ No newline at end of file
+</Project>
diff --git a/vsprojects/make.bat b/vsprojects/make.bat
index 04737ae..08c97bc 100644
--- a/vsprojects/make.bat
+++ b/vsprojects/make.bat
@@ -5,6 +5,7 @@
 @rem Set VS variables (uses Visual Studio 2013)
 @call "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" x86
 
-nmake /f Grpc.mak %*
+@rem /K: continue on error
+nmake /K /f Grpc.mak %*
 exit /b %ERRORLEVEL%
-endlocal
\ No newline at end of file
+endlocal