Selaa lähdekoodia

Merge pull request #4089 from yang-g/initial_string

Support sending an initial connect string at the beginning of client tcp connection.
Craig Tiller 10 vuotta sitten
vanhempi
commit
299bcd5521
45 muutettua tiedostoa jossa 1277 lisäystä ja 90 poistoa
  1. 9 0
      BUILD
  2. 1 0
      Makefile
  3. 2 0
      binding.gyp
  4. 28 0
      build.yaml
  5. 4 0
      gRPC.podspec
  6. 2 0
      src/core/client_config/connector.h
  7. 39 0
      src/core/client_config/default_initial_connect_string.c
  8. 53 0
      src/core/client_config/initial_connect_string.c
  9. 50 0
      src/core/client_config/initial_connect_string.h
  10. 7 0
      src/core/client_config/subchannel.c
  11. 1 0
      src/core/iomgr/pollset_posix.c
  12. 1 2
      src/core/iomgr/tcp_server.h
  13. 6 7
      src/core/iomgr/tcp_server_posix.c
  14. 5 5
      src/core/iomgr/tcp_server_windows.c
  15. 20 0
      src/core/surface/channel_create.c
  16. 26 2
      src/core/surface/secure_channel_create.c
  17. 2 1
      src/core/transport/chttp2/hpack_encoder.c
  18. 7 6
      test/core/client_config/lb_policies_test.c
  19. 221 0
      test/core/client_config/set_initial_connect_string_test.c
  20. 3 3
      test/core/end2end/tests/hpack_size.c
  21. 5 46
      test/core/util/reconnect_server.c
  22. 2 4
      test/core/util/reconnect_server.h
  23. 120 0
      test/core/util/test_tcp_server.c
  24. 55 0
      test/core/util/test_tcp_server.h
  25. 2 1
      test/cpp/interop/metrics_client.cc
  26. 13 3
      test/cpp/interop/reconnect_interop_server.cc
  27. 3 2
      test/cpp/qps/histogram.h
  28. 4 4
      test/cpp/qps/qps_driver.cc
  29. 1 1
      test/proto/benchmarks/stats.proto
  30. 2 1
      test/proto/metrics.proto
  31. 3 0
      tools/doxygen/Doxyfile.core.internal
  32. 44 2
      tools/run_tests/sources_and_headers.json
  33. 18 0
      tools/run_tests/tests.json
  34. 56 0
      vsprojects/buildtests_c.sln
  35. 28 0
      vsprojects/grpc.sln
  36. 5 0
      vsprojects/vcxproj/grpc/grpc.vcxproj
  37. 9 0
      vsprojects/vcxproj/grpc/grpc.vcxproj.filters
  38. 5 0
      vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
  39. 9 0
      vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
  40. 3 0
      vsprojects/vcxproj/reconnect_server/reconnect_server.vcxproj
  41. 3 0
      vsprojects/vcxproj/test/reconnect_interop_server/reconnect_interop_server.vcxproj
  42. 187 0
      vsprojects/vcxproj/test/set_initial_connect_string_test/set_initial_connect_string_test.vcxproj
  43. 21 0
      vsprojects/vcxproj/test/set_initial_connect_string_test/set_initial_connect_string_test.vcxproj.filters
  44. 166 0
      vsprojects/vcxproj/test_tcp_server/test_tcp_server.vcxproj
  45. 26 0
      vsprojects/vcxproj/test_tcp_server/test_tcp_server.vcxproj.filters

+ 9 - 0
BUILD

@@ -165,6 +165,7 @@ cc_library(
     "src/core/channel/subchannel_call_holder.h",
     "src/core/client_config/client_config.h",
     "src/core/client_config/connector.h",
+    "src/core/client_config/initial_connect_string.h",
     "src/core/client_config/lb_policies/pick_first.h",
     "src/core/client_config/lb_policies/round_robin.h",
     "src/core/client_config/lb_policy.h",
@@ -302,6 +303,8 @@ cc_library(
     "src/core/channel/subchannel_call_holder.c",
     "src/core/client_config/client_config.c",
     "src/core/client_config/connector.c",
+    "src/core/client_config/default_initial_connect_string.c",
+    "src/core/client_config/initial_connect_string.c",
     "src/core/client_config/lb_policies/pick_first.c",
     "src/core/client_config/lb_policies/round_robin.c",
     "src/core/client_config/lb_policy.c",
@@ -455,6 +458,7 @@ cc_library(
     "src/core/channel/subchannel_call_holder.h",
     "src/core/client_config/client_config.h",
     "src/core/client_config/connector.h",
+    "src/core/client_config/initial_connect_string.h",
     "src/core/client_config/lb_policies/pick_first.h",
     "src/core/client_config/lb_policies/round_robin.h",
     "src/core/client_config/lb_policy.h",
@@ -572,6 +576,8 @@ cc_library(
     "src/core/channel/subchannel_call_holder.c",
     "src/core/client_config/client_config.c",
     "src/core/client_config/connector.c",
+    "src/core/client_config/default_initial_connect_string.c",
+    "src/core/client_config/initial_connect_string.c",
     "src/core/client_config/lb_policies/pick_first.c",
     "src/core/client_config/lb_policies/round_robin.c",
     "src/core/client_config/lb_policy.c",
@@ -1103,6 +1109,8 @@ objc_library(
     "src/core/channel/subchannel_call_holder.c",
     "src/core/client_config/client_config.c",
     "src/core/client_config/connector.c",
+    "src/core/client_config/default_initial_connect_string.c",
+    "src/core/client_config/initial_connect_string.c",
     "src/core/client_config/lb_policies/pick_first.c",
     "src/core/client_config/lb_policies/round_robin.c",
     "src/core/client_config/lb_policy.c",
@@ -1253,6 +1261,7 @@ objc_library(
     "src/core/channel/subchannel_call_holder.h",
     "src/core/client_config/client_config.h",
     "src/core/client_config/connector.h",
+    "src/core/client_config/initial_connect_string.h",
     "src/core/client_config/lb_policies/pick_first.h",
     "src/core/client_config/lb_policies/round_robin.h",
     "src/core/client_config/lb_policy.h",

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 0
Makefile


+ 2 - 0
binding.gyp

@@ -187,6 +187,8 @@
         'src/core/channel/subchannel_call_holder.c',
         'src/core/client_config/client_config.c',
         'src/core/client_config/connector.c',
+        'src/core/client_config/default_initial_connect_string.c',
+        'src/core/client_config/initial_connect_string.c',
         'src/core/client_config/lb_policies/pick_first.c',
         'src/core/client_config/lb_policies/round_robin.c',
         'src/core/client_config/lb_policy.c',

+ 28 - 0
build.yaml

@@ -119,6 +119,7 @@ filegroups:
   - src/core/channel/subchannel_call_holder.h
   - src/core/client_config/client_config.h
   - src/core/client_config/connector.h
+  - src/core/client_config/initial_connect_string.h
   - src/core/client_config/lb_policies/pick_first.h
   - src/core/client_config/lb_policies/round_robin.h
   - src/core/client_config/lb_policy.h
@@ -233,6 +234,8 @@ filegroups:
   - src/core/channel/subchannel_call_holder.c
   - src/core/client_config/client_config.c
   - src/core/client_config/connector.c
+  - src/core/client_config/default_initial_connect_string.c
+  - src/core/client_config/initial_connect_string.c
   - src/core/client_config/lb_policies/pick_first.c
   - src/core/client_config/lb_policies/round_robin.c
   - src/core/client_config/lb_policy.c
@@ -581,6 +584,19 @@ libs:
   src:
   - test/core/util/reconnect_server.c
   deps:
+  - test_tcp_server
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
+- name: test_tcp_server
+  build: private
+  language: c
+  headers:
+  - test/core/util/test_tcp_server.h
+  src:
+  - test/core/util/test_tcp_server.c
+  deps:
   - grpc_test_util
   - grpc
   - gpr_test_util
@@ -1436,6 +1452,17 @@ targets:
   - grpc
   - gpr_test_util
   - gpr
+- name: set_initial_connect_string_test
+  build: test
+  language: c
+  src:
+  - test/core/client_config/set_initial_connect_string_test.c
+  deps:
+  - test_tcp_server
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
 - name: sockaddr_utils_test
   build: test
   language: c
@@ -2039,6 +2066,7 @@ targets:
   - test/cpp/interop/reconnect_interop_server.cc
   deps:
   - reconnect_server
+  - test_tcp_server
   - grpc++_test_util
   - grpc_test_util
   - grpc++

+ 4 - 0
gRPC.podspec

@@ -169,6 +169,7 @@ Pod::Spec.new do |s|
                       'src/core/channel/subchannel_call_holder.h',
                       'src/core/client_config/client_config.h',
                       'src/core/client_config/connector.h',
+                      'src/core/client_config/initial_connect_string.h',
                       'src/core/client_config/lb_policies/pick_first.h',
                       'src/core/client_config/lb_policies/round_robin.h',
                       'src/core/client_config/lb_policy.h',
@@ -313,6 +314,8 @@ Pod::Spec.new do |s|
                       'src/core/channel/subchannel_call_holder.c',
                       'src/core/client_config/client_config.c',
                       'src/core/client_config/connector.c',
+                      'src/core/client_config/default_initial_connect_string.c',
+                      'src/core/client_config/initial_connect_string.c',
                       'src/core/client_config/lb_policies/pick_first.c',
                       'src/core/client_config/lb_policies/round_robin.c',
                       'src/core/client_config/lb_policy.c',
@@ -465,6 +468,7 @@ Pod::Spec.new do |s|
                               'src/core/channel/subchannel_call_holder.h',
                               'src/core/client_config/client_config.h',
                               'src/core/client_config/connector.h',
+                              'src/core/client_config/initial_connect_string.h',
                               'src/core/client_config/lb_policies/pick_first.h',
                               'src/core/client_config/lb_policies/round_robin.h',
                               'src/core/client_config/lb_policy.h',

+ 2 - 0
src/core/client_config/connector.h

@@ -51,6 +51,8 @@ typedef struct {
   /** address to connect to */
   const struct sockaddr *addr;
   size_t addr_len;
+  /** initial connect string to send */
+  gpr_slice initial_connect_string;
   /** deadline for connection */
   gpr_timespec deadline;
   /** channel arguments (to be passed to transport) */

+ 39 - 0
src/core/client_config/default_initial_connect_string.c

@@ -0,0 +1,39 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <grpc/support/slice.h>
+#include "src/core/iomgr/sockaddr.h"
+
+void grpc_set_default_initial_connect_string(struct sockaddr **addr,
+                                             size_t *addr_len,
+                                             gpr_slice *initial_str) {}

+ 53 - 0
src/core/client_config/initial_connect_string.c

@@ -0,0 +1,53 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "src/core/client_config/initial_connect_string.h"
+
+#include <stddef.h>
+
+extern void grpc_set_default_initial_connect_string(struct sockaddr **addr,
+                                                    size_t *addr_len,
+                                                    gpr_slice *initial_str);
+
+static grpc_set_initial_connect_string_func g_set_initial_connect_string_func =
+    grpc_set_default_initial_connect_string;
+
+void grpc_test_set_initial_connect_string_function(
+    grpc_set_initial_connect_string_func func) {
+  g_set_initial_connect_string_func = func;
+}
+
+void grpc_set_initial_connect_string(struct sockaddr **addr, size_t *addr_len,
+                                     gpr_slice *initial_str) {
+  g_set_initial_connect_string_func(addr, addr_len, initial_str);
+}

+ 50 - 0
src/core/client_config/initial_connect_string.h

@@ -0,0 +1,50 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_INTERNAL_CORE_CLIENT_CONFIG_INITIAL_CONNECT_STRING_H
+#define GRPC_INTERNAL_CORE_CLIENT_CONFIG_INITIAL_CONNECT_STRING_H
+
+#include <grpc/support/slice.h>
+#include "src/core/iomgr/sockaddr.h"
+
+typedef void (*grpc_set_initial_connect_string_func)(struct sockaddr **addr,
+                                                     size_t *addr_len,
+                                                     gpr_slice *initial_str);
+void grpc_test_set_initial_connect_string_function(
+    grpc_set_initial_connect_string_func func);
+
+/** Set a string to be sent once connected. Optionally reset addr. */
+void grpc_set_initial_connect_string(struct sockaddr **addr, size_t *addr_len,
+                                     gpr_slice *connect_string);
+
+#endif /* GRPC_INTERNAL_CORE_CLIENT_CONFIG_INITIAL_CONNECT_STRING_H */

+ 7 - 0
src/core/client_config/subchannel.c

@@ -40,6 +40,7 @@
 #include "src/core/channel/channel_args.h"
 #include "src/core/channel/client_channel.h"
 #include "src/core/channel/connected_channel.h"
+#include "src/core/client_config/initial_connect_string.h"
 #include "src/core/iomgr/timer.h"
 #include "src/core/profiling/timers.h"
 #include "src/core/surface/channel.h"
@@ -87,6 +88,8 @@ struct grpc_subchannel {
   /** address to connect to */
   struct sockaddr *addr;
   size_t addr_len;
+  /** initial string to send to peer */
+  gpr_slice initial_connect_string;
   /** metadata context */
   grpc_mdctx *mdctx;
   /** master channel - the grpc_channel instance that ultimately owns
@@ -267,6 +270,7 @@ static void subchannel_destroy(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
   gpr_free((void *)c->filters);
   grpc_channel_args_destroy(c->args);
   gpr_free(c->addr);
+  gpr_slice_unref(c->initial_connect_string);
   grpc_mdctx_unref(c->mdctx);
   grpc_connectivity_state_destroy(exec_ctx, &c->state_tracker);
   grpc_connector_unref(exec_ctx, c->connector);
@@ -305,6 +309,8 @@ grpc_subchannel *grpc_subchannel_create(grpc_connector *connector,
   c->addr = gpr_malloc(args->addr_len);
   memcpy(c->addr, args->addr, args->addr_len);
   c->addr_len = args->addr_len;
+  grpc_set_initial_connect_string(&c->addr, &c->addr_len,
+                                  &c->initial_connect_string);
   c->args = grpc_channel_args_copy(args->args);
   c->mdctx = args->mdctx;
   c->master = args->master;
@@ -380,6 +386,7 @@ static void continue_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
   args.addr_len = c->addr_len;
   args.deadline = compute_connect_deadline(c);
   args.channel_args = c->args;
+  args.initial_connect_string = c->initial_connect_string;
 
   grpc_connector_connect(exec_ctx, c->connector, &args, &c->connecting_result,
                          &c->connected);

+ 1 - 0
src/core/iomgr/pollset_posix.c

@@ -194,6 +194,7 @@ void grpc_pollset_init(grpc_pollset *pollset) {
   pollset->in_flight_cbs = 0;
   pollset->shutting_down = 0;
   pollset->called_shutdown = 0;
+  pollset->kicked_without_pollers = 0;
   pollset->idle_jobs.head = pollset->idle_jobs.tail = NULL;
   pollset->local_wakeup_cache = NULL;
   pollset->kicked_without_pollers = 0;

+ 1 - 2
src/core/iomgr/tcp_server.h

@@ -64,8 +64,7 @@ void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *server,
 /* TODO(ctiller): deprecate this, and make grpc_tcp_server_add_ports to handle
                   all of the multiple socket port matching logic in one place */
 grpc_tcp_listener *grpc_tcp_server_add_port(grpc_tcp_server *s,
-                                            const void *addr,
-                                            size_t addr_len);
+                                            const void *addr, size_t addr_len);
 
 /* Returns the file descriptor of the Nth listening socket on this server,
    or -1 if the index is out of bounds.

+ 6 - 7
src/core/iomgr/tcp_server_posix.c

@@ -374,8 +374,8 @@ error:
 }
 
 static grpc_tcp_listener *add_socket_to_server(grpc_tcp_server *s, int fd,
-                                         const struct sockaddr *addr,
-                                         size_t addr_len) {
+                                               const struct sockaddr *addr,
+                                               size_t addr_len) {
   grpc_tcp_listener *sp = NULL;
   int port;
   char *addr_str;
@@ -410,8 +410,7 @@ static grpc_tcp_listener *add_socket_to_server(grpc_tcp_server *s, int fd,
 }
 
 grpc_tcp_listener *grpc_tcp_server_add_port(grpc_tcp_server *s,
-                                            const void *addr,
-                                            size_t addr_len) {
+                                            const void *addr, size_t addr_len) {
   int allocated_port = -1;
   grpc_tcp_listener *sp;
   grpc_tcp_listener *sp2 = NULL;
@@ -499,7 +498,8 @@ done:
 
 int grpc_tcp_server_get_fd(grpc_tcp_server *s, unsigned port_index) {
   grpc_tcp_listener *sp;
-  for (sp = s->head; sp && port_index != 0; sp = sp->next, port_index--);
+  for (sp = s->head; sp && port_index != 0; sp = sp->next, port_index--)
+    ;
   if (port_index == 0 && sp) {
     return sp->fd;
   } else {
@@ -527,8 +527,7 @@ void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
     }
     sp->read_closure.cb = on_read;
     sp->read_closure.cb_arg = sp;
-    grpc_fd_notify_on_read(exec_ctx, sp->emfd,
-                           &sp->read_closure);
+    grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure);
     s->active_ports++;
   }
   gpr_mu_unlock(&s->mu);

+ 5 - 5
src/core/iomgr/tcp_server_windows.c

@@ -352,8 +352,8 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, int from_iocp) {
 }
 
 static grpc_tcp_listener *add_socket_to_server(grpc_tcp_server *s, SOCKET sock,
-                                         const struct sockaddr *addr,
-                                         size_t addr_len) {
+                                               const struct sockaddr *addr,
+                                               size_t addr_len) {
   grpc_tcp_listener *sp = NULL;
   int port;
   int status;
@@ -400,8 +400,7 @@ static grpc_tcp_listener *add_socket_to_server(grpc_tcp_server *s, SOCKET sock,
 }
 
 grpc_tcp_listener *grpc_tcp_server_add_port(grpc_tcp_server *s,
-                                            const void *addr,
-                                            size_t addr_len) {
+                                            const void *addr, size_t addr_len) {
   grpc_tcp_listener *sp;
   SOCKET sock;
   struct sockaddr_in6 addr6_v4mapped;
@@ -459,7 +458,8 @@ grpc_tcp_listener *grpc_tcp_server_add_port(grpc_tcp_server *s,
 
 int grpc_tcp_server_get_fd(grpc_tcp_server *s, unsigned port_index) {
   grpc_tcp_listener *sp;
-  for (sp = s->head; sp && port_index != 0; sp = sp->next, port_index--);
+  for (sp = s->head; sp && port_index != 0; sp = sp->next, port_index--)
+    ;
   if (port_index == 0 && sp) {
     return _open_osfhandle(sp->socket->socket, 0);
   } else {

+ 20 - 0
src/core/surface/channel_create.c

@@ -37,6 +37,8 @@
 #include <string.h>
 
 #include <grpc/support/alloc.h>
+#include <grpc/support/slice.h>
+#include <grpc/support/slice_buffer.h>
 
 #include "src/core/census/grpc_filter.h"
 #include "src/core/channel/channel_args.h"
@@ -56,6 +58,8 @@ typedef struct {
   grpc_closure *notify;
   grpc_connect_in_args args;
   grpc_connect_out_args *result;
+  grpc_closure initial_string_sent;
+  gpr_slice_buffer initial_string_buffer;
 
   grpc_endpoint *tcp;
 
@@ -73,15 +77,31 @@ static void connector_unref(grpc_exec_ctx *exec_ctx, grpc_connector *con) {
   connector *c = (connector *)con;
   if (gpr_unref(&c->refs)) {
     grpc_mdctx_unref(c->mdctx);
+    /* c->initial_string_buffer does not need to be destroyed */
     gpr_free(c);
   }
 }
 
+static void on_initial_connect_string_sent(grpc_exec_ctx *exec_ctx, void *arg,
+                                           int success) {
+  connector_unref(exec_ctx, arg);
+}
+
 static void connected(grpc_exec_ctx *exec_ctx, void *arg, int success) {
   connector *c = arg;
   grpc_closure *notify;
   grpc_endpoint *tcp = c->tcp;
   if (tcp != NULL) {
+    if (!GPR_SLICE_IS_EMPTY(c->args.initial_connect_string)) {
+      grpc_closure_init(&c->initial_string_sent, on_initial_connect_string_sent,
+                        c);
+      gpr_slice_buffer_init(&c->initial_string_buffer);
+      gpr_slice_buffer_add(&c->initial_string_buffer,
+                           c->args.initial_connect_string);
+      connector_ref(arg);
+      grpc_endpoint_write(exec_ctx, tcp, &c->initial_string_buffer,
+                          &c->initial_string_sent);
+    }
     c->result->transport = grpc_create_chttp2_transport(
         exec_ctx, c->args.channel_args, tcp, c->mdctx, 1);
     grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, NULL,

+ 26 - 2
src/core/surface/secure_channel_create.c

@@ -37,6 +37,8 @@
 #include <string.h>
 
 #include <grpc/support/alloc.h>
+#include <grpc/support/slice.h>
+#include <grpc/support/slice_buffer.h>
 
 #include "src/core/census/grpc_filter.h"
 #include "src/core/channel/channel_args.h"
@@ -61,6 +63,8 @@ typedef struct {
   grpc_closure *notify;
   grpc_connect_in_args args;
   grpc_connect_out_args *result;
+  grpc_closure initial_string_sent;
+  gpr_slice_buffer initial_string_buffer;
 
   gpr_mu mu;
   grpc_endpoint *connecting_endpoint;
@@ -80,6 +84,7 @@ static void connector_unref(grpc_exec_ctx *exec_ctx, grpc_connector *con) {
   connector *c = (connector *)con;
   if (gpr_unref(&c->refs)) {
     grpc_mdctx_unref(c->mdctx);
+    /* c->initial_string_buffer does not need to be destroyed */
     gpr_free(c);
   }
 }
@@ -118,6 +123,14 @@ static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
   notify->cb(exec_ctx, notify->cb_arg, 1);
 }
 
+static void on_initial_connect_string_sent(grpc_exec_ctx *exec_ctx, void *arg,
+                                           int success) {
+  connector *c = arg;
+  grpc_security_connector_do_handshake(exec_ctx, &c->security_connector->base,
+                                       c->connecting_endpoint,
+                                       on_secure_handshake_done, c);
+}
+
 static void connected(grpc_exec_ctx *exec_ctx, void *arg, int success) {
   connector *c = arg;
   grpc_closure *notify;
@@ -127,8 +140,19 @@ static void connected(grpc_exec_ctx *exec_ctx, void *arg, int success) {
     GPR_ASSERT(c->connecting_endpoint == NULL);
     c->connecting_endpoint = tcp;
     gpr_mu_unlock(&c->mu);
-    grpc_security_connector_do_handshake(exec_ctx, &c->security_connector->base,
-                                         tcp, on_secure_handshake_done, c);
+    if (!GPR_SLICE_IS_EMPTY(c->args.initial_connect_string)) {
+      grpc_closure_init(&c->initial_string_sent, on_initial_connect_string_sent,
+                        c);
+      gpr_slice_buffer_init(&c->initial_string_buffer);
+      gpr_slice_buffer_add(&c->initial_string_buffer,
+                           c->args.initial_connect_string);
+      grpc_endpoint_write(exec_ctx, tcp, &c->initial_string_buffer,
+                          &c->initial_string_sent);
+    } else {
+      grpc_security_connector_do_handshake(exec_ctx,
+                                           &c->security_connector->base, tcp,
+                                           on_secure_handshake_done, c);
+    }
   } else {
     memset(c->result, 0, sizeof(*c->result));
     notify = c->notify;

+ 2 - 1
src/core/transport/chttp2/hpack_encoder.c

@@ -509,7 +509,8 @@ static void rebuild_elems(grpc_chttp2_hpack_compressor *c, gpr_uint32 new_cap) {
 
   for (i = 0; i < c->table_elems; i++) {
     gpr_uint32 ofs = c->tail_remote_index + i + 1;
-    table_elem_size[ofs % new_cap] = c->table_elem_size[ofs % c->cap_table_elems];
+    table_elem_size[ofs % new_cap] =
+        c->table_elem_size[ofs % c->cap_table_elems];
   }
 
   c->cap_table_elems = new_cap;

+ 7 - 6
test/core/client_config/lb_policies_test.c

@@ -135,8 +135,9 @@ static void kill_server(const servers_fixture *f, size_t i) {
   gpr_log(GPR_INFO, "KILLING SERVER %d", i);
   GPR_ASSERT(f->servers[i] != NULL);
   grpc_server_shutdown_and_notify(f->servers[i], f->cq, tag(10000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(10000), n_millis_time(5000),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(
+      grpc_completion_queue_pluck(f->cq, tag(10000), n_millis_time(5000), NULL)
+          .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->servers[i]);
   f->servers[i] = NULL;
 }
@@ -202,8 +203,8 @@ static void teardown_servers(servers_fixture *f) {
     if (f->servers[i] == NULL) continue;
     grpc_server_shutdown_and_notify(f->servers[i], f->cq, tag(10000));
     GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(10000),
-                                           n_millis_time(5000),
-                                           NULL).type == GRPC_OP_COMPLETE);
+                                           n_millis_time(5000), NULL)
+                   .type == GRPC_OP_COMPLETE);
     grpc_server_destroy(f->servers[i]);
   }
   grpc_completion_queue_shutdown(f->cq);
@@ -303,8 +304,8 @@ int *perform_request(servers_fixture *f, grpc_channel *client,
 
     s_idx = -1;
     while ((ev = grpc_completion_queue_next(
-                f->cq, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1), NULL)).type !=
-           GRPC_QUEUE_TIMEOUT) {
+                f->cq, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1), NULL))
+               .type != GRPC_QUEUE_TIMEOUT) {
       GPR_ASSERT(ev.type == GRPC_OP_COMPLETE);
       read_tag = ((int)(gpr_intptr)ev.tag);
       gpr_log(GPR_DEBUG, "EVENT: success:%d, type:%d, tag:%d iter:%d",

+ 221 - 0
test/core/client_config/set_initial_connect_string_test.c

@@ -0,0 +1,221 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include <string.h>
+
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/host_port.h>
+#include <grpc/support/log.h>
+#include <grpc/support/slice.h>
+
+#include "src/core/client_config/initial_connect_string.h"
+#include "src/core/iomgr/sockaddr.h"
+#include "src/core/security/credentials.h"
+#include "src/core/support/string.h"
+#include "test/core/util/port.h"
+#include "test/core/util/test_config.h"
+#include "test/core/util/test_tcp_server.h"
+
+struct rpc_state {
+  char *target;
+  grpc_channel_credentials *creds;
+  grpc_completion_queue *cq;
+  grpc_channel *channel;
+  grpc_call *call;
+  grpc_op op;
+  gpr_slice_buffer incoming_buffer;
+  gpr_slice_buffer temp_incoming_buffer;
+  grpc_endpoint *tcp;
+  int done;
+};
+
+static const char *magic_connect_string = "magic initial string";
+static int server_port;
+static struct rpc_state state;
+static grpc_closure on_read;
+
+static void handle_read(grpc_exec_ctx *exec_ctx, void *arg, int success) {
+  GPR_ASSERT(success);
+  gpr_slice_buffer_move_into(
+    &state.temp_incoming_buffer, &state.incoming_buffer);
+  if (state.incoming_buffer.length > strlen(magic_connect_string)) {
+    state.done = 1;
+    grpc_endpoint_shutdown(exec_ctx, state.tcp);
+    grpc_endpoint_destroy(exec_ctx, state.tcp);
+  } else {
+    grpc_endpoint_read(
+      exec_ctx, state.tcp, &state.temp_incoming_buffer, &on_read);
+  }
+}
+
+static void on_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp) {
+  test_tcp_server *server = arg;
+  grpc_closure_init(&on_read, handle_read, NULL);
+  gpr_slice_buffer_init(&state.incoming_buffer);
+  gpr_slice_buffer_init(&state.temp_incoming_buffer);
+  state.tcp = tcp;
+  grpc_endpoint_add_to_pollset(exec_ctx, tcp, &server->pollset);
+  grpc_endpoint_read(exec_ctx, tcp, &state.temp_incoming_buffer, &on_read);
+}
+
+static void set_magic_initial_string(struct sockaddr **addr, size_t *addr_len,
+                                     gpr_slice *connect_string) {
+  GPR_ASSERT(addr);
+  GPR_ASSERT(addr_len);
+  *connect_string = gpr_slice_from_copied_string(magic_connect_string);
+}
+
+static void reset_addr_and_set_magic_string(struct sockaddr **addr,
+                                            size_t *addr_len,
+                                            gpr_slice *connect_string) {
+  struct sockaddr_in target;
+  *connect_string = gpr_slice_from_copied_string(magic_connect_string);
+  gpr_free(*addr);
+  target.sin_family = AF_INET;
+  target.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+  target.sin_port = htons((uint16_t)server_port);
+  *addr_len = sizeof(target);
+  *addr = (struct sockaddr *)gpr_malloc(sizeof(target));
+  memcpy(*addr, &target, sizeof(target));
+}
+
+static gpr_timespec n_sec_deadline(int seconds) {
+  return gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
+                      gpr_time_from_seconds(seconds, GPR_TIMESPAN));
+}
+
+static void start_rpc(int use_creds, int target_port) {
+  state.done = 0;
+  state.cq = grpc_completion_queue_create(NULL);
+  if (use_creds) {
+    state.creds = grpc_fake_transport_security_credentials_create();
+  } else {
+    state.creds = NULL;
+  }
+  gpr_join_host_port(&state.target, "127.0.0.1", target_port);
+  if (use_creds) {
+    state.channel =
+        grpc_secure_channel_create(state.creds, state.target, NULL, NULL);
+  } else {
+    state.channel = grpc_insecure_channel_create(state.target, NULL, NULL);
+  }
+  state.call = grpc_channel_create_call(
+      state.channel, NULL, GRPC_PROPAGATE_DEFAULTS, state.cq, "/Service/Method",
+      "localhost", gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
+  state.op.op = GRPC_OP_SEND_INITIAL_METADATA;
+  state.op.data.send_initial_metadata.count = 0;
+  state.op.flags = 0;
+  state.op.reserved = NULL;
+  GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(state.call, &state.op,
+                                                   (size_t)(1), NULL, NULL));
+  grpc_completion_queue_next(state.cq, n_sec_deadline(1), NULL);
+}
+
+static void cleanup_rpc(void) {
+  grpc_event ev;
+  gpr_slice_buffer_destroy(&state.incoming_buffer);
+  gpr_slice_buffer_destroy(&state.temp_incoming_buffer);
+  grpc_channel_credentials_unref(state.creds);
+  grpc_call_destroy(state.call);
+  grpc_completion_queue_shutdown(state.cq);
+  do {
+    ev = grpc_completion_queue_next(state.cq, n_sec_deadline(1), NULL);
+  } while (ev.type != GRPC_QUEUE_SHUTDOWN);
+  grpc_completion_queue_destroy(state.cq);
+  grpc_channel_destroy(state.channel);
+  gpr_free(state.target);
+}
+
+static void poll_server_until_read_done(test_tcp_server *server) {
+  gpr_timespec deadline = n_sec_deadline(5);
+  while (state.done == 0 &&
+         gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0) {
+    test_tcp_server_poll(server, 1);
+  }
+}
+
+static void match_initial_magic_string(gpr_slice_buffer *buffer) {
+  size_t i, j, cmp_length;
+  size_t magic_length = strlen(magic_connect_string);
+  GPR_ASSERT(buffer->length >= magic_length);
+  for (i = 0, j = 0; i < state.incoming_buffer.count && j < magic_length; i++) {
+    char *dump =
+        gpr_dump_slice(state.incoming_buffer.slices[i], GPR_DUMP_ASCII);
+    cmp_length = GPR_MIN(strlen(dump), magic_length - j);
+    GPR_ASSERT(strncmp(dump, magic_connect_string + j, cmp_length) == 0);
+    j += cmp_length;
+    gpr_free(dump);
+  }
+}
+
+static void test_initial_string(test_tcp_server *server, int secure) {
+  grpc_test_set_initial_connect_string_function(set_magic_initial_string);
+  start_rpc(secure, server_port);
+  poll_server_until_read_done(server);
+  match_initial_magic_string(&state.incoming_buffer);
+  cleanup_rpc();
+}
+
+static void test_initial_string_with_redirect(test_tcp_server *server,
+                                              int secure) {
+  int another_port = grpc_pick_unused_port_or_die();
+  grpc_test_set_initial_connect_string_function(
+      reset_addr_and_set_magic_string);
+  start_rpc(secure, another_port);
+  poll_server_until_read_done(server);
+  match_initial_magic_string(&state.incoming_buffer);
+  cleanup_rpc();
+}
+
+static void run_test(void (*test)(test_tcp_server *server, int secure),
+                     int secure) {
+  test_tcp_server test_server;
+  server_port = grpc_pick_unused_port_or_die();
+  test_tcp_server_init(&test_server, on_connect, &test_server);
+  test_tcp_server_start(&test_server, server_port);
+  test(&test_server, secure);
+  test_tcp_server_destroy(&test_server);
+}
+
+int main(int argc, char **argv) {
+  grpc_test_init(argc, argv);
+  grpc_init();
+
+  run_test(test_initial_string, 0);
+  run_test(test_initial_string, 1);
+  run_test(test_initial_string_with_redirect, 0);
+  run_test(test_initial_string_with_redirect, 1);
+
+  grpc_shutdown();
+  return 0;
+}

+ 3 - 3
test/core/end2end/tests/hpack_size.c

@@ -262,9 +262,9 @@ static void drain_cq(grpc_completion_queue *cq) {
 static void shutdown_server(grpc_end2end_test_fixture *f) {
   if (!f->server) return;
   grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->cq, tag(1000),
-                                         GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5),
-                                         NULL).type == GRPC_OP_COMPLETE);
+  GPR_ASSERT(grpc_completion_queue_pluck(
+                 f->cq, tag(1000), GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5), NULL)
+                 .type == GRPC_OP_COMPLETE);
   grpc_server_destroy(f->server);
   f->server = NULL;
 }

+ 5 - 46
test/core/util/reconnect_server.c

@@ -44,6 +44,7 @@
 #include "src/core/iomgr/sockaddr.h"
 #include "src/core/iomgr/tcp_server.h"
 #include "test/core/util/port.h"
+#include "test/core/util/test_tcp_server.h"
 
 static void pretty_print_backoffs(reconnect_server *server) {
   gpr_timespec diff;
@@ -102,49 +103,18 @@ static void on_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp) {
 }
 
 void reconnect_server_init(reconnect_server *server) {
-  grpc_init();
-  server->tcp_server = NULL;
-  grpc_pollset_init(&server->pollset);
-  server->pollsets[0] = &server->pollset;
+  test_tcp_server_init(&server->tcp_server, on_connect, server);
   server->head = NULL;
   server->tail = NULL;
   server->peer = NULL;
 }
 
 void reconnect_server_start(reconnect_server *server, int port) {
-  struct sockaddr_in addr;
-  grpc_tcp_listener *listener;
-  int port_added;
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-
-  addr.sin_family = AF_INET;
-  addr.sin_port = htons((gpr_uint16)port);
-  memset(&addr.sin_addr, 0, sizeof(addr.sin_addr));
-
-  server->tcp_server = grpc_tcp_server_create();
-  listener = 
-      grpc_tcp_server_add_port(server->tcp_server, &addr, sizeof(addr));
-  port_added = grpc_tcp_listener_get_port(listener);
-  GPR_ASSERT(port_added == port);
-
-  grpc_tcp_server_start(&exec_ctx, server->tcp_server, server->pollsets, 1,
-                        on_connect, server);
-  gpr_log(GPR_INFO, "reconnect tcp server listening on 0.0.0.0:%d", port);
-
-  grpc_exec_ctx_finish(&exec_ctx);
+  test_tcp_server_start(&server->tcp_server, port);
 }
 
 void reconnect_server_poll(reconnect_server *server, int seconds) {
-  grpc_pollset_worker worker;
-  gpr_timespec deadline =
-      gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
-                   gpr_time_from_seconds(seconds, GPR_TIMESPAN));
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  gpr_mu_lock(GRPC_POLLSET_MU(&server->pollset));
-  grpc_pollset_work(&exec_ctx, &server->pollset, &worker,
-                    gpr_now(GPR_CLOCK_MONOTONIC), deadline);
-  gpr_mu_unlock(GRPC_POLLSET_MU(&server->pollset));
-  grpc_exec_ctx_finish(&exec_ctx);
+  test_tcp_server_poll(&server->tcp_server, seconds);
 }
 
 void reconnect_server_clear_timestamps(reconnect_server *server) {
@@ -159,18 +129,7 @@ void reconnect_server_clear_timestamps(reconnect_server *server) {
   server->peer = NULL;
 }
 
-static void do_nothing(grpc_exec_ctx *exec_ctx, void *ignored, int success) {}
-
 void reconnect_server_destroy(reconnect_server *server) {
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_closure do_nothing_closure[2];
-  grpc_closure_init(&do_nothing_closure[0], do_nothing, NULL);
-  grpc_closure_init(&do_nothing_closure[1], do_nothing, NULL);
-  grpc_tcp_server_destroy(&exec_ctx, server->tcp_server,
-                          &do_nothing_closure[0]);
   reconnect_server_clear_timestamps(server);
-  grpc_pollset_shutdown(&exec_ctx, &server->pollset, &do_nothing_closure[1]);
-  grpc_exec_ctx_finish(&exec_ctx);
-  grpc_pollset_destroy(&server->pollset);
-  grpc_shutdown();
+  test_tcp_server_destroy(&server->tcp_server);
 }

+ 2 - 4
test/core/util/reconnect_server.h

@@ -36,7 +36,7 @@
 
 #include <grpc/support/sync.h>
 #include <grpc/support/time.h>
-#include "src/core/iomgr/tcp_server.h"
+#include "test/core/util/test_tcp_server.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -48,9 +48,7 @@ typedef struct timestamp_list {
 } timestamp_list;
 
 typedef struct reconnect_server {
-  grpc_tcp_server *tcp_server;
-  grpc_pollset pollset;
-  grpc_pollset *pollsets[1];
+  test_tcp_server tcp_server;
   timestamp_list *head;
   timestamp_list *tail;
   char *peer;

+ 120 - 0
test/core/util/test_tcp_server.c

@@ -0,0 +1,120 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "test/core/util/test_tcp_server.h"
+
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/host_port.h>
+#include <grpc/support/log.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/time.h>
+#include <string.h>
+#include "src/core/iomgr/endpoint.h"
+#include "src/core/iomgr/sockaddr.h"
+#include "src/core/iomgr/tcp_server.h"
+#include "test/core/util/port.h"
+
+void test_tcp_server_init(test_tcp_server *server,
+                          grpc_tcp_server_cb on_connect, void *user_data) {
+  grpc_init();
+  server->tcp_server = NULL;
+  server->shutdown = 0;
+  grpc_pollset_init(&server->pollset);
+  server->pollsets[0] = &server->pollset;
+  server->on_connect = on_connect;
+  server->cb_data = user_data;
+}
+
+void test_tcp_server_start(test_tcp_server *server, int port) {
+  struct sockaddr_in addr;
+  grpc_tcp_listener *listener;
+  int port_added;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+
+  addr.sin_family = AF_INET;
+  addr.sin_port = htons((gpr_uint16)port);
+  memset(&addr.sin_addr, 0, sizeof(addr.sin_addr));
+
+  server->tcp_server = grpc_tcp_server_create();
+  listener = grpc_tcp_server_add_port(server->tcp_server, &addr, sizeof(addr));
+  port_added = grpc_tcp_listener_get_port(listener);
+  GPR_ASSERT(port_added == port);
+
+  grpc_tcp_server_start(&exec_ctx, server->tcp_server, server->pollsets, 1,
+                        server->on_connect, server->cb_data);
+  gpr_log(GPR_INFO, "test tcp server listening on 0.0.0.0:%d", port);
+
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+
+void test_tcp_server_poll(test_tcp_server *server, int seconds) {
+  grpc_pollset_worker worker;
+  gpr_timespec deadline =
+      gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
+                   gpr_time_from_seconds(seconds, GPR_TIMESPAN));
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  gpr_mu_lock(GRPC_POLLSET_MU(&server->pollset));
+  grpc_pollset_work(&exec_ctx, &server->pollset, &worker,
+                    gpr_now(GPR_CLOCK_MONOTONIC), deadline);
+  gpr_mu_unlock(GRPC_POLLSET_MU(&server->pollset));
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+
+static void on_server_destroyed(grpc_exec_ctx *exec_ctx, void *data,
+                                int success) {
+  test_tcp_server *server = data;
+  server->shutdown = 1;
+}
+
+static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, int success) {}
+
+void test_tcp_server_destroy(test_tcp_server *server) {
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  gpr_timespec shutdown_deadline;
+  grpc_closure server_shutdown_cb;
+  grpc_closure do_nothing_cb;
+  grpc_closure_init(&server_shutdown_cb, on_server_destroyed, server);
+  grpc_closure_init(&do_nothing_cb, do_nothing, NULL);
+  grpc_tcp_server_destroy(&exec_ctx, server->tcp_server, &server_shutdown_cb);
+  shutdown_deadline = gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
+                                   gpr_time_from_seconds(5, GPR_TIMESPAN));
+  while (!server->shutdown &&
+         gpr_time_cmp(gpr_now(GPR_CLOCK_MONOTONIC), shutdown_deadline) < 0) {
+    test_tcp_server_poll(server, 1);
+  }
+  grpc_pollset_shutdown(&exec_ctx, &server->pollset, &do_nothing_cb);
+  grpc_exec_ctx_finish(&exec_ctx);
+  grpc_pollset_destroy(&server->pollset);
+  grpc_shutdown();
+}

+ 55 - 0
test/core/util/test_tcp_server.h

@@ -0,0 +1,55 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_TEST_CORE_UTIL_TEST_TCP_SERVER_H
+#define GRPC_TEST_CORE_UTIL_TEST_TCP_SERVER_H
+
+#include <grpc/support/sync.h>
+#include "src/core/iomgr/tcp_server.h"
+
+typedef struct test_tcp_server {
+  grpc_tcp_server *tcp_server;
+  int shutdown;
+  grpc_pollset pollset;
+  grpc_pollset *pollsets[1];
+  grpc_tcp_server_cb on_connect;
+  void *cb_data;
+} test_tcp_server;
+
+void test_tcp_server_init(test_tcp_server *server,
+                          grpc_tcp_server_cb on_connect, void *user_data);
+void test_tcp_server_start(test_tcp_server *server, int port);
+void test_tcp_server_poll(test_tcp_server *server, int seconds);
+void test_tcp_server_destroy(test_tcp_server *server);
+
+#endif /* GRPC_TEST_CORE_UTIL_TEST_TCP_SERVER_H */

+ 2 - 1
test/cpp/interop/metrics_client.cc

@@ -72,7 +72,8 @@ void PrintMetrics(grpc::string& server_address) {
               gauge_response.name().c_str(), gauge_response.long_value());
       overall_qps += gauge_response.long_value();
     } else {
-      gpr_log(GPR_INFO, "Gauge %s is not a long value", gauge_response.name().c_str());
+      gpr_log(GPR_INFO, "Gauge %s is not a long value",
+              gauge_response.name().c_str());
     }
   }
 

+ 13 - 3
test/cpp/interop/reconnect_interop_server.cc

@@ -75,12 +75,15 @@ static bool got_sigint = false;
 class ReconnectServiceImpl : public ReconnectService::Service {
  public:
   explicit ReconnectServiceImpl(int retry_port)
-      : retry_port_(retry_port), serving_(false), shutdown_(false) {
+      : retry_port_(retry_port),
+        serving_(false),
+        server_started_(false),
+        shutdown_(false) {
     reconnect_server_init(&tcp_server_);
   }
 
   ~ReconnectServiceImpl() {
-    if (tcp_server_.tcp_server) {
+    if (server_started_) {
       reconnect_server_destroy(&tcp_server_);
     }
   }
@@ -88,6 +91,7 @@ class ReconnectServiceImpl : public ReconnectService::Service {
   void Poll(int seconds) { reconnect_server_poll(&tcp_server_, seconds); }
 
   Status Start(ServerContext* context, const Empty* request, Empty* response) {
+    bool start_server = true;
     std::unique_lock<std::mutex> lock(mu_);
     while (serving_ && !shutdown_) {
       cv_.wait(lock);
@@ -96,9 +100,14 @@ class ReconnectServiceImpl : public ReconnectService::Service {
       return Status(grpc::StatusCode::UNAVAILABLE, "shutting down");
     }
     serving_ = true;
+    if (server_started_) {
+      start_server = false;
+    } else {
+      server_started_ = true;
+    }
     lock.unlock();
 
-    if (!tcp_server_.tcp_server) {
+    if (start_server) {
       reconnect_server_start(&tcp_server_, retry_port_);
     } else {
       reconnect_server_clear_timestamps(&tcp_server_);
@@ -152,6 +161,7 @@ class ReconnectServiceImpl : public ReconnectService::Service {
   int retry_port_;
   reconnect_server tcp_server_;
   bool serving_;
+  bool server_started_;
   bool shutdown_;
   std::mutex mu_;
   std::condition_variable cv_;

+ 3 - 2
test/cpp/qps/histogram.h

@@ -43,8 +43,9 @@ namespace testing {
 class Histogram {
  public:
   // TODO: look into making histogram params not hardcoded for C++
-  Histogram() : impl_(gpr_histogram_create(default_resolution(),
-                                           default_max_possible())) {}
+  Histogram()
+      : impl_(gpr_histogram_create(default_resolution(),
+                                   default_max_possible())) {}
   ~Histogram() {
     if (impl_) gpr_histogram_destroy(impl_);
   }

+ 4 - 4
test/cpp/qps/qps_driver.cc

@@ -137,10 +137,10 @@ static void QpsDriver() {
     // No further load parameters to set up for closed loop
   }
 
-  client_config.mutable_histogram_params()->
-      set_resolution(Histogram::default_resolution());
-  client_config.mutable_histogram_params()->
-      set_max_possible(Histogram::default_max_possible());
+  client_config.mutable_histogram_params()->set_resolution(
+      Histogram::default_resolution());
+  client_config.mutable_histogram_params()->set_max_possible(
+      Histogram::default_max_possible());
 
   ServerConfig server_config;
   server_config.set_server_type(server_type);

+ 1 - 1
test/proto/benchmarks/stats.proto

@@ -45,7 +45,7 @@ message ServerStats {
 
 // Histogram params based on grpc/support/histogram.c
 message HistogramParams {
-  double resolution = 1;  // first bucket is [0, 1 + resolution)
+  double resolution = 1;    // first bucket is [0, 1 + resolution)
   double max_possible = 2;  // use enough buckets to allow this value
 }
 

+ 2 - 1
test/proto/metrics.proto

@@ -47,7 +47,8 @@ message GaugeRequest {
   string name = 1;
 }
 
-message EmptyMessage {}
+message EmptyMessage {
+}
 
 service MetricsService {
   rpc GetAllGauges(EmptyMessage) returns (stream GaugeResponse);

+ 3 - 0
tools/doxygen/Doxyfile.core.internal

@@ -794,6 +794,7 @@ src/core/channel/noop_filter.h \
 src/core/channel/subchannel_call_holder.h \
 src/core/client_config/client_config.h \
 src/core/client_config/connector.h \
+src/core/client_config/initial_connect_string.h \
 src/core/client_config/lb_policies/pick_first.h \
 src/core/client_config/lb_policies/round_robin.h \
 src/core/client_config/lb_policy.h \
@@ -931,6 +932,8 @@ src/core/channel/noop_filter.c \
 src/core/channel/subchannel_call_holder.c \
 src/core/client_config/client_config.c \
 src/core/client_config/connector.c \
+src/core/client_config/default_initial_connect_string.c \
+src/core/client_config/initial_connect_string.c \
 src/core/client_config/lb_policies/pick_first.c \
 src/core/client_config/lb_policies/round_robin.c \
 src/core/client_config/lb_policy.c \

+ 44 - 2
tools/run_tests/sources_and_headers.json

@@ -866,6 +866,21 @@
       "test/core/security/secure_endpoint_test.c"
     ]
   }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util", 
+      "test_tcp_server"
+    ], 
+    "headers": [], 
+    "language": "c", 
+    "name": "set_initial_connect_string_test", 
+    "src": [
+      "test/core/client_config/set_initial_connect_string_test.c"
+    ]
+  }, 
   {
     "deps": [
       "gpr", 
@@ -1572,7 +1587,8 @@
       "grpc++_test_config", 
       "grpc++_test_util", 
       "grpc_test_util", 
-      "reconnect_server"
+      "reconnect_server", 
+      "test_tcp_server"
     ], 
     "headers": [
       "test/proto/empty.grpc.pb.h", 
@@ -14348,6 +14364,7 @@
       "src/core/channel/subchannel_call_holder.h", 
       "src/core/client_config/client_config.h", 
       "src/core/client_config/connector.h", 
+      "src/core/client_config/initial_connect_string.h", 
       "src/core/client_config/lb_policies/pick_first.h", 
       "src/core/client_config/lb_policies/round_robin.h", 
       "src/core/client_config/lb_policy.h", 
@@ -14506,6 +14523,9 @@
       "src/core/client_config/client_config.h", 
       "src/core/client_config/connector.c", 
       "src/core/client_config/connector.h", 
+      "src/core/client_config/default_initial_connect_string.c", 
+      "src/core/client_config/initial_connect_string.c", 
+      "src/core/client_config/initial_connect_string.h", 
       "src/core/client_config/lb_policies/pick_first.c", 
       "src/core/client_config/lb_policies/pick_first.h", 
       "src/core/client_config/lb_policies/round_robin.c", 
@@ -14860,6 +14880,7 @@
       "src/core/channel/subchannel_call_holder.h", 
       "src/core/client_config/client_config.h", 
       "src/core/client_config/connector.h", 
+      "src/core/client_config/initial_connect_string.h", 
       "src/core/client_config/lb_policies/pick_first.h", 
       "src/core/client_config/lb_policies/round_robin.h", 
       "src/core/client_config/lb_policy.h", 
@@ -15004,6 +15025,9 @@
       "src/core/client_config/client_config.h", 
       "src/core/client_config/connector.c", 
       "src/core/client_config/connector.h", 
+      "src/core/client_config/default_initial_connect_string.c", 
+      "src/core/client_config/initial_connect_string.c", 
+      "src/core/client_config/initial_connect_string.h", 
       "src/core/client_config/lb_policies/pick_first.c", 
       "src/core/client_config/lb_policies/pick_first.h", 
       "src/core/client_config/lb_policies/round_robin.c", 
@@ -15238,7 +15262,8 @@
       "gpr", 
       "gpr_test_util", 
       "grpc", 
-      "grpc_test_util"
+      "grpc_test_util", 
+      "test_tcp_server"
     ], 
     "headers": [
       "test/core/util/reconnect_server.h"
@@ -15250,6 +15275,23 @@
       "test/core/util/reconnect_server.h"
     ]
   }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [
+      "test/core/util/test_tcp_server.h"
+    ], 
+    "language": "c", 
+    "name": "test_tcp_server", 
+    "src": [
+      "test/core/util/test_tcp_server.c", 
+      "test/core/util/test_tcp_server.h"
+    ]
+  }, 
   {
     "deps": [
       "gpr", 

+ 18 - 0
tools/run_tests/tests.json

@@ -977,6 +977,24 @@
       "windows"
     ]
   }, 
+  {
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "exclude_configs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "set_initial_connect_string_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ]
+  }, 
   {
     "ci_platforms": [
       "linux", 

+ 56 - 0
vsprojects/buildtests_c.sln

@@ -53,6 +53,18 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc_unsecure", "vcxproj\.\
 	EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "reconnect_server", "vcxproj\.\reconnect_server\reconnect_server.vcxproj", "{929C90AE-483F-AC80-EF93-226199F9E428}"
+	ProjectSection(myProperties) = preProject
+        	lib = "True"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{E3110C46-A148-FF65-08FD-3324829BE7FE} = {E3110C46-A148-FF65-08FD-3324829BE7FE}
+		{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
+		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_tcp_server", "vcxproj\.\test_tcp_server\test_tcp_server.vcxproj", "{E3110C46-A148-FF65-08FD-3324829BE7FE}"
 	ProjectSection(myProperties) = preProject
         	lib = "True"
 	EndProjectSection
@@ -1200,6 +1212,18 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "secure_endpoint_test", "vcx
 		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
 	EndProjectSection
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "set_initial_connect_string_test", "vcxproj\test\set_initial_connect_string_test\set_initial_connect_string_test.vcxproj", "{4A48E5A5-2E69-ED6D-063C-C297180A54D0}"
+	ProjectSection(myProperties) = preProject
+        	lib = "False"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{E3110C46-A148-FF65-08FD-3324829BE7FE} = {E3110C46-A148-FF65-08FD-3324829BE7FE}
+		{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
+		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sockaddr_utils_test", "vcxproj\test\sockaddr_utils_test\sockaddr_utils_test.vcxproj", "{529771F0-10B0-9B1A-1E7E-8A8E01870348}"
 	ProjectSection(myProperties) = preProject
         	lib = "False"
@@ -9609,6 +9633,22 @@ Global
 		{929C90AE-483F-AC80-EF93-226199F9E428}.Release-DLL|Win32.Build.0 = Release|Win32
 		{929C90AE-483F-AC80-EF93-226199F9E428}.Release-DLL|x64.ActiveCfg = Release|x64
 		{929C90AE-483F-AC80-EF93-226199F9E428}.Release-DLL|x64.Build.0 = Release|x64
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Debug|Win32.ActiveCfg = Debug|Win32
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Debug|x64.ActiveCfg = Debug|x64
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Release|Win32.ActiveCfg = Release|Win32
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Release|x64.ActiveCfg = Release|x64
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Debug|Win32.Build.0 = Debug|Win32
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Debug|x64.Build.0 = Debug|x64
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Release|Win32.Build.0 = Release|Win32
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Release|x64.Build.0 = Release|x64
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Debug-DLL|x64.Build.0 = Debug|x64
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Release-DLL|Win32.Build.0 = Release|Win32
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Release-DLL|x64.ActiveCfg = Release|x64
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Release-DLL|x64.Build.0 = Release|x64
 		{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}.Debug|Win32.ActiveCfg = Debug|Win32
 		{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}.Debug|x64.ActiveCfg = Debug|x64
 		{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}.Release|Win32.ActiveCfg = Release|Win32
@@ -11337,6 +11377,22 @@ Global
 		{A7747106-A6BC-62D4-2A21-04A4F0CC2683}.Release-DLL|Win32.Build.0 = Release|Win32
 		{A7747106-A6BC-62D4-2A21-04A4F0CC2683}.Release-DLL|x64.ActiveCfg = Release|x64
 		{A7747106-A6BC-62D4-2A21-04A4F0CC2683}.Release-DLL|x64.Build.0 = Release|x64
+		{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Debug|Win32.ActiveCfg = Debug|Win32
+		{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Debug|x64.ActiveCfg = Debug|x64
+		{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Release|Win32.ActiveCfg = Release|Win32
+		{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Release|x64.ActiveCfg = Release|x64
+		{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Debug|Win32.Build.0 = Debug|Win32
+		{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Debug|x64.Build.0 = Debug|x64
+		{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Release|Win32.Build.0 = Release|Win32
+		{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Release|x64.Build.0 = Release|x64
+		{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Debug-DLL|x64.Build.0 = Debug|x64
+		{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Release-DLL|Win32.Build.0 = Release|Win32
+		{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Release-DLL|x64.ActiveCfg = Release|x64
+		{4A48E5A5-2E69-ED6D-063C-C297180A54D0}.Release-DLL|x64.Build.0 = Release|x64
 		{529771F0-10B0-9B1A-1E7E-8A8E01870348}.Debug|Win32.ActiveCfg = Debug|Win32
 		{529771F0-10B0-9B1A-1E7E-8A8E01870348}.Debug|x64.ActiveCfg = Debug|x64
 		{529771F0-10B0-9B1A-1E7E-8A8E01870348}.Release|Win32.ActiveCfg = Release|Win32

+ 28 - 0
vsprojects/grpc.sln

@@ -53,6 +53,18 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "grpc_unsecure", "vcxproj\.\
 	EndProjectSection
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "reconnect_server", "vcxproj\.\reconnect_server\reconnect_server.vcxproj", "{929C90AE-483F-AC80-EF93-226199F9E428}"
+	ProjectSection(myProperties) = preProject
+        	lib = "True"
+	EndProjectSection
+	ProjectSection(ProjectDependencies) = postProject
+		{E3110C46-A148-FF65-08FD-3324829BE7FE} = {E3110C46-A148-FF65-08FD-3324829BE7FE}
+		{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B} = {17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}
+		{29D16885-7228-4C31-81ED-5F9187C7F2A9} = {29D16885-7228-4C31-81ED-5F9187C7F2A9}
+		{EAB0A629-17A9-44DB-B5FF-E91A721FE037} = {EAB0A629-17A9-44DB-B5FF-E91A721FE037}
+		{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792} = {B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}
+	EndProjectSection
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_tcp_server", "vcxproj\.\test_tcp_server\test_tcp_server.vcxproj", "{E3110C46-A148-FF65-08FD-3324829BE7FE}"
 	ProjectSection(myProperties) = preProject
         	lib = "True"
 	EndProjectSection
@@ -263,6 +275,22 @@ Global
 		{929C90AE-483F-AC80-EF93-226199F9E428}.Release-DLL|Win32.Build.0 = Release|Win32
 		{929C90AE-483F-AC80-EF93-226199F9E428}.Release-DLL|x64.ActiveCfg = Release|x64
 		{929C90AE-483F-AC80-EF93-226199F9E428}.Release-DLL|x64.Build.0 = Release|x64
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Debug|Win32.ActiveCfg = Debug|Win32
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Debug|x64.ActiveCfg = Debug|x64
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Release|Win32.ActiveCfg = Release|Win32
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Release|x64.ActiveCfg = Release|x64
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Debug|Win32.Build.0 = Debug|Win32
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Debug|x64.Build.0 = Debug|x64
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Release|Win32.Build.0 = Release|Win32
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Release|x64.Build.0 = Release|x64
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Debug-DLL|Win32.ActiveCfg = Debug|Win32
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Debug-DLL|Win32.Build.0 = Debug|Win32
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Debug-DLL|x64.ActiveCfg = Debug|x64
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Debug-DLL|x64.Build.0 = Debug|x64
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Release-DLL|Win32.ActiveCfg = Release|Win32
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Release-DLL|Win32.Build.0 = Release|Win32
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Release-DLL|x64.ActiveCfg = Release|x64
+		{E3110C46-A148-FF65-08FD-3324829BE7FE}.Release-DLL|x64.Build.0 = Release|x64
 		{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}.Debug|Win32.ActiveCfg = Debug|Win32
 		{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}.Debug|x64.ActiveCfg = Debug|x64
 		{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}.Release|Win32.ActiveCfg = Release|Win32

+ 5 - 0
vsprojects/vcxproj/grpc/grpc.vcxproj

@@ -280,6 +280,7 @@
     <ClInclude Include="..\..\..\src\core\channel\subchannel_call_holder.h" />
     <ClInclude Include="..\..\..\src\core\client_config\client_config.h" />
     <ClInclude Include="..\..\..\src\core\client_config\connector.h" />
+    <ClInclude Include="..\..\..\src\core\client_config\initial_connect_string.h" />
     <ClInclude Include="..\..\..\src\core\client_config\lb_policies\pick_first.h" />
     <ClInclude Include="..\..\..\src\core\client_config\lb_policies\round_robin.h" />
     <ClInclude Include="..\..\..\src\core\client_config\lb_policy.h" />
@@ -454,6 +455,10 @@
     </ClCompile>
     <ClCompile Include="..\..\..\src\core\client_config\connector.c">
     </ClCompile>
+    <ClCompile Include="..\..\..\src\core\client_config\default_initial_connect_string.c">
+    </ClCompile>
+    <ClCompile Include="..\..\..\src\core\client_config\initial_connect_string.c">
+    </ClCompile>
     <ClCompile Include="..\..\..\src\core\client_config\lb_policies\pick_first.c">
     </ClCompile>
     <ClCompile Include="..\..\..\src\core\client_config\lb_policies\round_robin.c">

+ 9 - 0
vsprojects/vcxproj/grpc/grpc.vcxproj.filters

@@ -106,6 +106,12 @@
     <ClCompile Include="..\..\..\src\core\client_config\connector.c">
       <Filter>src\core\client_config</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\..\src\core\client_config\default_initial_connect_string.c">
+      <Filter>src\core\client_config</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\src\core\client_config\initial_connect_string.c">
+      <Filter>src\core\client_config</Filter>
+    </ClCompile>
     <ClCompile Include="..\..\..\src\core\client_config\lb_policies\pick_first.c">
       <Filter>src\core\client_config\lb_policies</Filter>
     </ClCompile>
@@ -554,6 +560,9 @@
     <ClInclude Include="..\..\..\src\core\client_config\connector.h">
       <Filter>src\core\client_config</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\..\src\core\client_config\initial_connect_string.h">
+      <Filter>src\core\client_config</Filter>
+    </ClInclude>
     <ClInclude Include="..\..\..\src\core\client_config\lb_policies\pick_first.h">
       <Filter>src\core\client_config\lb_policies</Filter>
     </ClInclude>

+ 5 - 0
vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj

@@ -259,6 +259,7 @@
     <ClInclude Include="..\..\..\src\core\channel\subchannel_call_holder.h" />
     <ClInclude Include="..\..\..\src\core\client_config\client_config.h" />
     <ClInclude Include="..\..\..\src\core\client_config\connector.h" />
+    <ClInclude Include="..\..\..\src\core\client_config\initial_connect_string.h" />
     <ClInclude Include="..\..\..\src\core\client_config\lb_policies\pick_first.h" />
     <ClInclude Include="..\..\..\src\core\client_config\lb_policies\round_robin.h" />
     <ClInclude Include="..\..\..\src\core\client_config\lb_policy.h" />
@@ -393,6 +394,10 @@
     </ClCompile>
     <ClCompile Include="..\..\..\src\core\client_config\connector.c">
     </ClCompile>
+    <ClCompile Include="..\..\..\src\core\client_config\default_initial_connect_string.c">
+    </ClCompile>
+    <ClCompile Include="..\..\..\src\core\client_config\initial_connect_string.c">
+    </ClCompile>
     <ClCompile Include="..\..\..\src\core\client_config\lb_policies\pick_first.c">
     </ClCompile>
     <ClCompile Include="..\..\..\src\core\client_config\lb_policies\round_robin.c">

+ 9 - 0
vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters

@@ -46,6 +46,12 @@
     <ClCompile Include="..\..\..\src\core\client_config\connector.c">
       <Filter>src\core\client_config</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\..\src\core\client_config\default_initial_connect_string.c">
+      <Filter>src\core\client_config</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\..\src\core\client_config\initial_connect_string.c">
+      <Filter>src\core\client_config</Filter>
+    </ClCompile>
     <ClCompile Include="..\..\..\src\core\client_config\lb_policies\pick_first.c">
       <Filter>src\core\client_config\lb_policies</Filter>
     </ClCompile>
@@ -452,6 +458,9 @@
     <ClInclude Include="..\..\..\src\core\client_config\connector.h">
       <Filter>src\core\client_config</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\..\src\core\client_config\initial_connect_string.h">
+      <Filter>src\core\client_config</Filter>
+    </ClInclude>
     <ClInclude Include="..\..\..\src\core\client_config\lb_policies\pick_first.h">
       <Filter>src\core\client_config\lb_policies</Filter>
     </ClInclude>

+ 3 - 0
vsprojects/vcxproj/reconnect_server/reconnect_server.vcxproj

@@ -141,6 +141,9 @@
     </ClCompile>
   </ItemGroup>
   <ItemGroup>
+    <ProjectReference Include="..\..\..\vsprojects\vcxproj\.\test_tcp_server\test_tcp_server.vcxproj">
+      <Project>{E3110C46-A148-FF65-08FD-3324829BE7FE}</Project>
+    </ProjectReference>
     <ProjectReference Include="..\..\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
       <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
     </ProjectReference>

+ 3 - 0
vsprojects/vcxproj/test/reconnect_interop_server/reconnect_interop_server.vcxproj

@@ -176,6 +176,9 @@
     <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\reconnect_server\reconnect_server.vcxproj">
       <Project>{929C90AE-483F-AC80-EF93-226199F9E428}</Project>
     </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\test_tcp_server\test_tcp_server.vcxproj">
+      <Project>{E3110C46-A148-FF65-08FD-3324829BE7FE}</Project>
+    </ProjectReference>
     <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc++_test_util\grpc++_test_util.vcxproj">
       <Project>{0BE77741-552A-929B-A497-4EF7ECE17A64}</Project>
     </ProjectReference>

+ 187 - 0
vsprojects/vcxproj/test/set_initial_connect_string_test/set_initial_connect_string_test.vcxproj

@@ -0,0 +1,187 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\1.0.2.3.props')" />
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{4A48E5A5-2E69-ED6D-063C-C297180A54D0}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="..\..\..\..\vsprojects\global.props" />
+    <Import Project="..\..\..\..\vsprojects\openssl.props" />
+    <Import Project="..\..\..\..\vsprojects\winsock.props" />
+    <Import Project="..\..\..\..\vsprojects\zlib.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>set_initial_connect_string_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>set_initial_connect_string_test</TargetName>
+    <Linkage-grpc_dependencies_zlib>static</Linkage-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_zlib>Debug</Configuration-grpc_dependencies_zlib>
+    <Configuration-grpc_dependencies_openssl>Debug</Configuration-grpc_dependencies_openssl>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\..\..\test\core\client_config\set_initial_connect_string_test.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\test_tcp_server\test_tcp_server.vcxproj">
+      <Project>{E3110C46-A148-FF65-08FD-3324829BE7FE}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies\grpc.dependencies.zlib.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  <Import Project="..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets" Condition="Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies\grpc.dependencies.openssl.targets')" />
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.redist.1.2.8.9\build\native\grpc.dependencies.zlib.redist.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.zlib.1.2.8.9\build\native\grpc.dependencies.zlib.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.redist.1.0.2.3\build\native\grpc.dependencies.openssl.redist.targets')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.props')" />
+    <Error Condition="!Exists('..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\vsprojects\packages\grpc.dependencies.openssl.1.0.2.3\build\native\grpc.dependencies.openssl.targets')" />
+  </Target>
+</Project>
+

+ 21 - 0
vsprojects/vcxproj/test/set_initial_connect_string_test/set_initial_connect_string_test.vcxproj.filters

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="..\..\..\..\test\core\client_config\set_initial_connect_string_test.c">
+      <Filter>test\core\client_config</Filter>
+    </ClCompile>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="test">
+      <UniqueIdentifier>{413358e4-3165-f09d-071c-ee4f2ca0b826}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core">
+      <UniqueIdentifier>{a554b5ef-0c80-ac03-1848-bccd947a06a6}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core\client_config">
+      <UniqueIdentifier>{a6c4917f-b1b0-e958-6ea8-34950c2f8f36}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+

+ 166 - 0
vsprojects/vcxproj/test_tcp_server/test_tcp_server.vcxproj

@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{E3110C46-A148-FF65-08FD-3324829BE7FE}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '10.0'" Label="Configuration">
+    <PlatformToolset>v100</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '11.0'" Label="Configuration">
+    <PlatformToolset>v110</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(VisualStudioVersion)' == '12.0'" Label="Configuration">
+    <PlatformToolset>v120</PlatformToolset>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
+    <ConfigurationType>StaticLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+    <Import Project="..\..\..\vsprojects\global.props" />
+    <Import Project="..\..\..\vsprojects\winsock.props" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)'=='Debug'">
+    <TargetName>test_tcp_server</TargetName>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)'=='Release'">
+    <TargetName>test_tcp_server</TargetName>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_USE_32BIT_TIME_T;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <SDLCheck>true</SDLCheck>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+      <TreatWarningAsError>true</TreatWarningAsError>
+      <DebugInformationFormat Condition="$(Jenkins)">None</DebugInformationFormat>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation Condition="!$(Jenkins)">true</GenerateDebugInformation>
+      <GenerateDebugInformation Condition="$(Jenkins)">false</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\..\test\core\util\test_tcp_server.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\..\test\core\util\test_tcp_server.c">
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\vsprojects\vcxproj\.\grpc_test_util\grpc_test_util.vcxproj">
+      <Project>{17BCAFC0-5FDC-4C94-AEB9-95F3E220614B}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\vsprojects\vcxproj\.\grpc\grpc.vcxproj">
+      <Project>{29D16885-7228-4C31-81ED-5F9187C7F2A9}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\vsprojects\vcxproj\.\gpr_test_util\gpr_test_util.vcxproj">
+      <Project>{EAB0A629-17A9-44DB-B5FF-E91A721FE037}</Project>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\vsprojects\vcxproj\.\gpr\gpr.vcxproj">
+      <Project>{B23D3D1A-9438-4EDA-BEB6-9A0A03D17792}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+    <PropertyGroup>
+      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+    </PropertyGroup>
+  </Target>
+</Project>
+

+ 26 - 0
vsprojects/vcxproj/test_tcp_server/test_tcp_server.vcxproj.filters

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <ClCompile Include="..\..\..\test\core\util\test_tcp_server.c">
+      <Filter>test\core\util</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\..\test\core\util\test_tcp_server.h">
+      <Filter>test\core\util</Filter>
+    </ClInclude>
+  </ItemGroup>
+
+  <ItemGroup>
+    <Filter Include="test">
+      <UniqueIdentifier>{28134501-94bd-f7ba-b77b-c4863be94758}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core">
+      <UniqueIdentifier>{6e538eb5-ce76-212d-d785-e8450b89f1ba}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="test\core\util">
+      <UniqueIdentifier>{f33a1bbf-69a0-d776-ab7c-2fd5c382b6d3}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+</Project>
+

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä