Selaa lähdekoodia

Merge branch 'master' into httpplumbing

Yash Tibrewal 6 vuotta sitten
vanhempi
commit
248e304671
100 muutettua tiedostoa jossa 1663 lisäystä ja 784 poistoa
  1. 9 0
      .gitmodules
  2. 5 5
      BUILD
  3. 7 7
      CMakeLists.txt
  4. 15 15
      Makefile
  5. 10 10
      README.md
  6. 4 4
      build.yaml
  7. 3 2
      config.m4
  8. 1 1
      config.w32
  9. 2 1
      doc/g_stands_for.md
  10. 4 4
      gRPC-C++.podspec
  11. 4 4
      gRPC-Core.podspec
  12. 1 1
      gRPC-ProtoRPC.podspec
  13. 1 1
      gRPC-RxLibrary.podspec
  14. 1 1
      gRPC.podspec
  15. 2 2
      grpc.gemspec
  16. 4 4
      grpc.gyp
  17. 4 4
      include/grpcpp/channel.h
  18. 2 2
      include/grpcpp/create_channel.h
  19. 1 2
      include/grpcpp/impl/codegen/completion_queue.h
  20. 6 6
      include/grpcpp/security/credentials.h
  21. 2 2
      include/grpcpp/server.h
  22. 4 4
      package.xml
  23. 37 0
      src/compiler/csharp_generator.cc
  24. 23 142
      src/core/ext/filters/client_channel/client_channel.cc
  25. 6 3
      src/core/ext/filters/client_channel/lb_policy.h
  26. 4 3
      src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
  27. 5 3
      src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
  28. 5 3
      src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
  29. 7 3
      src/core/ext/filters/client_channel/lb_policy/xds/xds.cc
  30. 5 0
      src/core/ext/filters/client_channel/lb_policy_registry.cc
  31. 4 0
      src/core/ext/filters/client_channel/lb_policy_registry.h
  32. 0 178
      src/core/ext/filters/client_channel/method_params.cc
  33. 0 78
      src/core/ext/filters/client_channel/method_params.h
  34. 5 18
      src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc
  35. 15 2
      src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc
  36. 4 0
      src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h
  37. 384 0
      src/core/ext/filters/client_channel/resolver_result_parsing.cc
  38. 146 0
      src/core/ext/filters/client_channel/resolver_result_parsing.h
  39. 57 16
      src/core/lib/gprpp/ref_counted.h
  40. 1 1
      src/core/lib/surface/version.cc
  41. 3 5
      src/cpp/client/channel_cc.cc
  42. 5 4
      src/cpp/client/client_context.cc
  43. 19 17
      src/cpp/client/create_channel.cc
  44. 2 2
      src/cpp/client/create_channel_internal.cc
  45. 2 2
      src/cpp/client/create_channel_internal.h
  46. 6 4
      src/cpp/client/create_channel_posix.cc
  47. 6 3
      src/cpp/client/cronet_credentials.cc
  48. 6 3
      src/cpp/client/insecure_credentials.cc
  49. 6 3
      src/cpp/client/secure_credentials.cc
  50. 2 2
      src/cpp/client/secure_credentials.h
  51. 1 1
      src/cpp/common/version_cc.cc
  52. 5 7
      src/cpp/server/server_cc.cc
  53. 1 1
      src/csharp/Grpc.Core.Tests/Internal/AsyncCallServerTest.cs
  54. 2 5
      src/csharp/Grpc.Core.Tests/MarshallerTest.cs
  55. 6 1
      src/csharp/Grpc.Core/DeserializationContext.cs
  56. 1 1
      src/csharp/Grpc.Core/Internal/AsyncCall.cs
  57. 22 5
      src/csharp/Grpc.Core/Internal/AsyncCallBase.cs
  58. 1 1
      src/csharp/Grpc.Core/Internal/AsyncCallServer.cs
  59. 66 0
      src/csharp/Grpc.Core/Internal/DefaultDeserializationContext.cs
  60. 62 0
      src/csharp/Grpc.Core/Internal/DefaultSerializationContext.cs
  61. 8 8
      src/csharp/Grpc.Core/Internal/ServerCallHandler.cs
  62. 6 61
      src/csharp/Grpc.Core/Marshaller.cs
  63. 6 1
      src/csharp/Grpc.Core/SerializationContext.cs
  64. 4 4
      src/csharp/Grpc.Core/ServerServiceDefinition.cs
  65. 101 0
      src/csharp/Grpc.Core/ServiceBinderBase.cs
  66. 1 1
      src/csharp/Grpc.Core/Version.csproj.include
  67. 2 2
      src/csharp/Grpc.Core/VersionInfo.cs
  68. 12 0
      src/csharp/Grpc.Examples/MathGrpc.cs
  69. 13 7
      src/csharp/Grpc.HealthCheck/Health.cs
  70. 134 1
      src/csharp/Grpc.HealthCheck/HealthGrpc.cs
  71. 13 0
      src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs
  72. 89 55
      src/csharp/Grpc.IntegrationTesting/Control.cs
  73. 8 0
      src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs
  74. 10 0
      src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs
  75. 9 0
      src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs
  76. 35 0
      src/csharp/Grpc.IntegrationTesting/TestGrpc.cs
  77. 12 0
      src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs
  78. 9 0
      src/csharp/Grpc.Reflection/ReflectionGrpc.cs
  79. 1 1
      src/csharp/build_packages_dotnetcli.bat
  80. 1 1
      src/csharp/build_unitypackage.bat
  81. 1 1
      src/objective-c/!ProtoCompiler-gRPCPlugin.podspec
  82. 1 1
      src/objective-c/GRPCClient/private/version.h
  83. 1 1
      src/objective-c/tests/version.h
  84. 1 1
      src/php/composer.json
  85. 2 0
      src/php/ext/grpc/channel.c
  86. 3 0
      src/php/ext/grpc/channel.h
  87. 1 1
      src/php/ext/grpc/config.m4
  88. 120 0
      src/php/ext/grpc/php_grpc.c
  89. 1 1
      src/php/ext/grpc/version.h
  90. 1 1
      src/python/grpcio/grpc/_grpcio_metadata.py
  91. 1 1
      src/python/grpcio/grpc_core_dependencies.py
  92. 1 1
      src/python/grpcio/grpc_version.py
  93. 1 1
      src/python/grpcio_health_checking/grpc_version.py
  94. 1 1
      src/python/grpcio_reflection/grpc_version.py
  95. 1 1
      src/python/grpcio_testing/grpc_version.py
  96. 1 1
      src/python/grpcio_tests/grpc_version.py
  97. 24 27
      src/python/grpcio_tests/tests/unit/_server_ssl_cert_config_test.py
  98. 1 1
      src/ruby/lib/grpc/version.rb
  99. 1 1
      src/ruby/tools/version.rb
  100. 1 1
      templates/Makefile.template

+ 9 - 0
.gitmodules

@@ -42,3 +42,12 @@
 	path = third_party/libcxx
 	path = third_party/libcxx
 	url = https://github.com/llvm-mirror/libcxx.git
 	url = https://github.com/llvm-mirror/libcxx.git
 	branch = release_60
 	branch = release_60
+[submodule "third_party/data-plane-api"]
+	path = third_party/data-plane-api
+	url = https://github.com/envoyproxy/data-plane-api.git
+[submodule "third_party/googleapis"]
+	path = third_party/googleapis
+	url = https://github.com/googleapis/googleapis.git
+[submodule "third_party/protoc-gen-validate"]
+	path = third_party/protoc-gen-validate
+	url = https://github.com/lyft/protoc-gen-validate.git

+ 5 - 5
BUILD

@@ -64,11 +64,11 @@ config_setting(
 )
 )
 
 
 # This should be updated along with build.yaml
 # This should be updated along with build.yaml
-g_stands_for = "gizmo"
+g_stands_for = "goose"
 
 
-core_version = "6.0.0-dev"
+core_version = "7.0.0-dev"
 
 
-version = "1.17.0-dev"
+version = "1.18.0-dev"
 
 
 GPR_PUBLIC_HDRS = [
 GPR_PUBLIC_HDRS = [
     "include/grpc/support/alloc.h",
     "include/grpc/support/alloc.h",
@@ -1048,12 +1048,12 @@ grpc_cc_library(
         "src/core/ext/filters/client_channel/lb_policy.cc",
         "src/core/ext/filters/client_channel/lb_policy.cc",
         "src/core/ext/filters/client_channel/lb_policy_factory.cc",
         "src/core/ext/filters/client_channel/lb_policy_factory.cc",
         "src/core/ext/filters/client_channel/lb_policy_registry.cc",
         "src/core/ext/filters/client_channel/lb_policy_registry.cc",
-        "src/core/ext/filters/client_channel/method_params.cc",
         "src/core/ext/filters/client_channel/parse_address.cc",
         "src/core/ext/filters/client_channel/parse_address.cc",
         "src/core/ext/filters/client_channel/proxy_mapper.cc",
         "src/core/ext/filters/client_channel/proxy_mapper.cc",
         "src/core/ext/filters/client_channel/proxy_mapper_registry.cc",
         "src/core/ext/filters/client_channel/proxy_mapper_registry.cc",
         "src/core/ext/filters/client_channel/resolver.cc",
         "src/core/ext/filters/client_channel/resolver.cc",
         "src/core/ext/filters/client_channel/resolver_registry.cc",
         "src/core/ext/filters/client_channel/resolver_registry.cc",
+        "src/core/ext/filters/client_channel/resolver_result_parsing.cc",
         "src/core/ext/filters/client_channel/retry_throttle.cc",
         "src/core/ext/filters/client_channel/retry_throttle.cc",
         "src/core/ext/filters/client_channel/subchannel.cc",
         "src/core/ext/filters/client_channel/subchannel.cc",
         "src/core/ext/filters/client_channel/subchannel_index.cc",
         "src/core/ext/filters/client_channel/subchannel_index.cc",
@@ -1070,13 +1070,13 @@ grpc_cc_library(
         "src/core/ext/filters/client_channel/lb_policy.h",
         "src/core/ext/filters/client_channel/lb_policy.h",
         "src/core/ext/filters/client_channel/lb_policy_factory.h",
         "src/core/ext/filters/client_channel/lb_policy_factory.h",
         "src/core/ext/filters/client_channel/lb_policy_registry.h",
         "src/core/ext/filters/client_channel/lb_policy_registry.h",
-        "src/core/ext/filters/client_channel/method_params.h",
         "src/core/ext/filters/client_channel/parse_address.h",
         "src/core/ext/filters/client_channel/parse_address.h",
         "src/core/ext/filters/client_channel/proxy_mapper.h",
         "src/core/ext/filters/client_channel/proxy_mapper.h",
         "src/core/ext/filters/client_channel/proxy_mapper_registry.h",
         "src/core/ext/filters/client_channel/proxy_mapper_registry.h",
         "src/core/ext/filters/client_channel/resolver.h",
         "src/core/ext/filters/client_channel/resolver.h",
         "src/core/ext/filters/client_channel/resolver_factory.h",
         "src/core/ext/filters/client_channel/resolver_factory.h",
         "src/core/ext/filters/client_channel/resolver_registry.h",
         "src/core/ext/filters/client_channel/resolver_registry.h",
+        "src/core/ext/filters/client_channel/resolver_result_parsing.h",
         "src/core/ext/filters/client_channel/retry_throttle.h",
         "src/core/ext/filters/client_channel/retry_throttle.h",
         "src/core/ext/filters/client_channel/subchannel.h",
         "src/core/ext/filters/client_channel/subchannel.h",
         "src/core/ext/filters/client_channel/subchannel_index.h",
         "src/core/ext/filters/client_channel/subchannel_index.h",

+ 7 - 7
CMakeLists.txt

@@ -24,7 +24,7 @@
 cmake_minimum_required(VERSION 2.8)
 cmake_minimum_required(VERSION 2.8)
 
 
 set(PACKAGE_NAME      "grpc")
 set(PACKAGE_NAME      "grpc")
-set(PACKAGE_VERSION   "1.17.0-dev")
+set(PACKAGE_VERSION   "1.18.0-dev")
 set(PACKAGE_STRING    "${PACKAGE_NAME} ${PACKAGE_VERSION}")
 set(PACKAGE_STRING    "${PACKAGE_NAME} ${PACKAGE_VERSION}")
 set(PACKAGE_TARNAME   "${PACKAGE_NAME}-${PACKAGE_VERSION}")
 set(PACKAGE_TARNAME   "${PACKAGE_NAME}-${PACKAGE_VERSION}")
 set(PACKAGE_BUGREPORT "https://github.com/grpc/grpc/issues/")
 set(PACKAGE_BUGREPORT "https://github.com/grpc/grpc/issues/")
@@ -1242,12 +1242,12 @@ add_library(grpc
   src/core/ext/filters/client_channel/lb_policy.cc
   src/core/ext/filters/client_channel/lb_policy.cc
   src/core/ext/filters/client_channel/lb_policy_factory.cc
   src/core/ext/filters/client_channel/lb_policy_factory.cc
   src/core/ext/filters/client_channel/lb_policy_registry.cc
   src/core/ext/filters/client_channel/lb_policy_registry.cc
-  src/core/ext/filters/client_channel/method_params.cc
   src/core/ext/filters/client_channel/parse_address.cc
   src/core/ext/filters/client_channel/parse_address.cc
   src/core/ext/filters/client_channel/proxy_mapper.cc
   src/core/ext/filters/client_channel/proxy_mapper.cc
   src/core/ext/filters/client_channel/proxy_mapper_registry.cc
   src/core/ext/filters/client_channel/proxy_mapper_registry.cc
   src/core/ext/filters/client_channel/resolver.cc
   src/core/ext/filters/client_channel/resolver.cc
   src/core/ext/filters/client_channel/resolver_registry.cc
   src/core/ext/filters/client_channel/resolver_registry.cc
+  src/core/ext/filters/client_channel/resolver_result_parsing.cc
   src/core/ext/filters/client_channel/retry_throttle.cc
   src/core/ext/filters/client_channel/retry_throttle.cc
   src/core/ext/filters/client_channel/subchannel.cc
   src/core/ext/filters/client_channel/subchannel.cc
   src/core/ext/filters/client_channel/subchannel_index.cc
   src/core/ext/filters/client_channel/subchannel_index.cc
@@ -1594,12 +1594,12 @@ add_library(grpc_cronet
   src/core/ext/filters/client_channel/lb_policy.cc
   src/core/ext/filters/client_channel/lb_policy.cc
   src/core/ext/filters/client_channel/lb_policy_factory.cc
   src/core/ext/filters/client_channel/lb_policy_factory.cc
   src/core/ext/filters/client_channel/lb_policy_registry.cc
   src/core/ext/filters/client_channel/lb_policy_registry.cc
-  src/core/ext/filters/client_channel/method_params.cc
   src/core/ext/filters/client_channel/parse_address.cc
   src/core/ext/filters/client_channel/parse_address.cc
   src/core/ext/filters/client_channel/proxy_mapper.cc
   src/core/ext/filters/client_channel/proxy_mapper.cc
   src/core/ext/filters/client_channel/proxy_mapper_registry.cc
   src/core/ext/filters/client_channel/proxy_mapper_registry.cc
   src/core/ext/filters/client_channel/resolver.cc
   src/core/ext/filters/client_channel/resolver.cc
   src/core/ext/filters/client_channel/resolver_registry.cc
   src/core/ext/filters/client_channel/resolver_registry.cc
+  src/core/ext/filters/client_channel/resolver_result_parsing.cc
   src/core/ext/filters/client_channel/retry_throttle.cc
   src/core/ext/filters/client_channel/retry_throttle.cc
   src/core/ext/filters/client_channel/subchannel.cc
   src/core/ext/filters/client_channel/subchannel.cc
   src/core/ext/filters/client_channel/subchannel_index.cc
   src/core/ext/filters/client_channel/subchannel_index.cc
@@ -1965,12 +1965,12 @@ add_library(grpc_test_util
   src/core/ext/filters/client_channel/lb_policy.cc
   src/core/ext/filters/client_channel/lb_policy.cc
   src/core/ext/filters/client_channel/lb_policy_factory.cc
   src/core/ext/filters/client_channel/lb_policy_factory.cc
   src/core/ext/filters/client_channel/lb_policy_registry.cc
   src/core/ext/filters/client_channel/lb_policy_registry.cc
-  src/core/ext/filters/client_channel/method_params.cc
   src/core/ext/filters/client_channel/parse_address.cc
   src/core/ext/filters/client_channel/parse_address.cc
   src/core/ext/filters/client_channel/proxy_mapper.cc
   src/core/ext/filters/client_channel/proxy_mapper.cc
   src/core/ext/filters/client_channel/proxy_mapper_registry.cc
   src/core/ext/filters/client_channel/proxy_mapper_registry.cc
   src/core/ext/filters/client_channel/resolver.cc
   src/core/ext/filters/client_channel/resolver.cc
   src/core/ext/filters/client_channel/resolver_registry.cc
   src/core/ext/filters/client_channel/resolver_registry.cc
+  src/core/ext/filters/client_channel/resolver_result_parsing.cc
   src/core/ext/filters/client_channel/retry_throttle.cc
   src/core/ext/filters/client_channel/retry_throttle.cc
   src/core/ext/filters/client_channel/subchannel.cc
   src/core/ext/filters/client_channel/subchannel.cc
   src/core/ext/filters/client_channel/subchannel_index.cc
   src/core/ext/filters/client_channel/subchannel_index.cc
@@ -2285,12 +2285,12 @@ add_library(grpc_test_util_unsecure
   src/core/ext/filters/client_channel/lb_policy.cc
   src/core/ext/filters/client_channel/lb_policy.cc
   src/core/ext/filters/client_channel/lb_policy_factory.cc
   src/core/ext/filters/client_channel/lb_policy_factory.cc
   src/core/ext/filters/client_channel/lb_policy_registry.cc
   src/core/ext/filters/client_channel/lb_policy_registry.cc
-  src/core/ext/filters/client_channel/method_params.cc
   src/core/ext/filters/client_channel/parse_address.cc
   src/core/ext/filters/client_channel/parse_address.cc
   src/core/ext/filters/client_channel/proxy_mapper.cc
   src/core/ext/filters/client_channel/proxy_mapper.cc
   src/core/ext/filters/client_channel/proxy_mapper_registry.cc
   src/core/ext/filters/client_channel/proxy_mapper_registry.cc
   src/core/ext/filters/client_channel/resolver.cc
   src/core/ext/filters/client_channel/resolver.cc
   src/core/ext/filters/client_channel/resolver_registry.cc
   src/core/ext/filters/client_channel/resolver_registry.cc
+  src/core/ext/filters/client_channel/resolver_result_parsing.cc
   src/core/ext/filters/client_channel/retry_throttle.cc
   src/core/ext/filters/client_channel/retry_throttle.cc
   src/core/ext/filters/client_channel/subchannel.cc
   src/core/ext/filters/client_channel/subchannel.cc
   src/core/ext/filters/client_channel/subchannel_index.cc
   src/core/ext/filters/client_channel/subchannel_index.cc
@@ -2619,12 +2619,12 @@ add_library(grpc_unsecure
   src/core/ext/filters/client_channel/lb_policy.cc
   src/core/ext/filters/client_channel/lb_policy.cc
   src/core/ext/filters/client_channel/lb_policy_factory.cc
   src/core/ext/filters/client_channel/lb_policy_factory.cc
   src/core/ext/filters/client_channel/lb_policy_registry.cc
   src/core/ext/filters/client_channel/lb_policy_registry.cc
-  src/core/ext/filters/client_channel/method_params.cc
   src/core/ext/filters/client_channel/parse_address.cc
   src/core/ext/filters/client_channel/parse_address.cc
   src/core/ext/filters/client_channel/proxy_mapper.cc
   src/core/ext/filters/client_channel/proxy_mapper.cc
   src/core/ext/filters/client_channel/proxy_mapper_registry.cc
   src/core/ext/filters/client_channel/proxy_mapper_registry.cc
   src/core/ext/filters/client_channel/resolver.cc
   src/core/ext/filters/client_channel/resolver.cc
   src/core/ext/filters/client_channel/resolver_registry.cc
   src/core/ext/filters/client_channel/resolver_registry.cc
+  src/core/ext/filters/client_channel/resolver_result_parsing.cc
   src/core/ext/filters/client_channel/retry_throttle.cc
   src/core/ext/filters/client_channel/retry_throttle.cc
   src/core/ext/filters/client_channel/subchannel.cc
   src/core/ext/filters/client_channel/subchannel.cc
   src/core/ext/filters/client_channel/subchannel_index.cc
   src/core/ext/filters/client_channel/subchannel_index.cc
@@ -3471,12 +3471,12 @@ add_library(grpc++_cronet
   src/core/ext/filters/client_channel/lb_policy.cc
   src/core/ext/filters/client_channel/lb_policy.cc
   src/core/ext/filters/client_channel/lb_policy_factory.cc
   src/core/ext/filters/client_channel/lb_policy_factory.cc
   src/core/ext/filters/client_channel/lb_policy_registry.cc
   src/core/ext/filters/client_channel/lb_policy_registry.cc
-  src/core/ext/filters/client_channel/method_params.cc
   src/core/ext/filters/client_channel/parse_address.cc
   src/core/ext/filters/client_channel/parse_address.cc
   src/core/ext/filters/client_channel/proxy_mapper.cc
   src/core/ext/filters/client_channel/proxy_mapper.cc
   src/core/ext/filters/client_channel/proxy_mapper_registry.cc
   src/core/ext/filters/client_channel/proxy_mapper_registry.cc
   src/core/ext/filters/client_channel/resolver.cc
   src/core/ext/filters/client_channel/resolver.cc
   src/core/ext/filters/client_channel/resolver_registry.cc
   src/core/ext/filters/client_channel/resolver_registry.cc
+  src/core/ext/filters/client_channel/resolver_result_parsing.cc
   src/core/ext/filters/client_channel/retry_throttle.cc
   src/core/ext/filters/client_channel/retry_throttle.cc
   src/core/ext/filters/client_channel/subchannel.cc
   src/core/ext/filters/client_channel/subchannel.cc
   src/core/ext/filters/client_channel/subchannel_index.cc
   src/core/ext/filters/client_channel/subchannel_index.cc

+ 15 - 15
Makefile

@@ -438,8 +438,8 @@ Q = @
 endif
 endif
 
 
 CORE_VERSION = 7.0.0-dev
 CORE_VERSION = 7.0.0-dev
-CPP_VERSION = 1.17.0-dev
-CSHARP_VERSION = 1.17.0-dev
+CPP_VERSION = 1.18.0-dev
+CSHARP_VERSION = 1.18.0-dev
 
 
 CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES))
 CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES))
 CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS)
 CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS)
@@ -3069,7 +3069,7 @@ install-shared_cxx: shared_cxx strip-shared_cxx install-shared_c install-pkg-con
 ifeq ($(SYSTEM),MINGW32)
 ifeq ($(SYSTEM),MINGW32)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP)-dll.a $(prefix)/lib/libgrpc++.a
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++$(SHARED_VERSION_CPP)-dll.a $(prefix)/lib/libgrpc++.a
 else ifneq ($(SYSTEM),Darwin)
 else ifneq ($(SYSTEM),Darwin)
-	$(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++.so.7
+	$(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++.so.1
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++.so
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++.so
 endif
 endif
 	$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)"
 	$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)"
@@ -3078,7 +3078,7 @@ endif
 ifeq ($(SYSTEM),MINGW32)
 ifeq ($(SYSTEM),MINGW32)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP)-dll.a $(prefix)/lib/libgrpc++_cronet.a
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_cronet$(SHARED_VERSION_CPP)-dll.a $(prefix)/lib/libgrpc++_cronet.a
 else ifneq ($(SYSTEM),Darwin)
 else ifneq ($(SYSTEM),Darwin)
-	$(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_cronet.so.7
+	$(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_cronet.so.1
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_cronet.so
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++_cronet$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_cronet.so
 endif
 endif
 	$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++_error_details$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)"
 	$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++_error_details$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)"
@@ -3087,7 +3087,7 @@ endif
 ifeq ($(SYSTEM),MINGW32)
 ifeq ($(SYSTEM),MINGW32)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_error_details$(SHARED_VERSION_CPP)-dll.a $(prefix)/lib/libgrpc++_error_details.a
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_error_details$(SHARED_VERSION_CPP)-dll.a $(prefix)/lib/libgrpc++_error_details.a
 else ifneq ($(SYSTEM),Darwin)
 else ifneq ($(SYSTEM),Darwin)
-	$(Q) ln -sf $(SHARED_PREFIX)grpc++_error_details$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_error_details.so.7
+	$(Q) ln -sf $(SHARED_PREFIX)grpc++_error_details$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_error_details.so.1
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++_error_details$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_error_details.so
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++_error_details$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_error_details.so
 endif
 endif
 	$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)"
 	$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)"
@@ -3096,7 +3096,7 @@ endif
 ifeq ($(SYSTEM),MINGW32)
 ifeq ($(SYSTEM),MINGW32)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP)-dll.a $(prefix)/lib/libgrpc++_reflection.a
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_reflection$(SHARED_VERSION_CPP)-dll.a $(prefix)/lib/libgrpc++_reflection.a
 else ifneq ($(SYSTEM),Darwin)
 else ifneq ($(SYSTEM),Darwin)
-	$(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_reflection.so.7
+	$(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_reflection.so.1
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_reflection.so
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++_reflection$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_reflection.so
 endif
 endif
 	$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)"
 	$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)"
@@ -3105,7 +3105,7 @@ endif
 ifeq ($(SYSTEM),MINGW32)
 ifeq ($(SYSTEM),MINGW32)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP)-dll.a $(prefix)/lib/libgrpc++_unsecure.a
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure$(SHARED_VERSION_CPP)-dll.a $(prefix)/lib/libgrpc++_unsecure.a
 else ifneq ($(SYSTEM),Darwin)
 else ifneq ($(SYSTEM),Darwin)
-	$(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_unsecure.so.7
+	$(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_unsecure.so.1
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_unsecure.so
 	$(Q) ln -sf $(SHARED_PREFIX)grpc++_unsecure$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpc++_unsecure.so
 endif
 endif
 	$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpcpp_channelz$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)"
 	$(E) "[INSTALL] Installing $(SHARED_PREFIX)grpcpp_channelz$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP)"
@@ -3114,7 +3114,7 @@ endif
 ifeq ($(SYSTEM),MINGW32)
 ifeq ($(SYSTEM),MINGW32)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpcpp_channelz$(SHARED_VERSION_CPP)-dll.a $(prefix)/lib/libgrpcpp_channelz.a
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpcpp_channelz$(SHARED_VERSION_CPP)-dll.a $(prefix)/lib/libgrpcpp_channelz.a
 else ifneq ($(SYSTEM),Darwin)
 else ifneq ($(SYSTEM),Darwin)
-	$(Q) ln -sf $(SHARED_PREFIX)grpcpp_channelz$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpcpp_channelz.so.7
+	$(Q) ln -sf $(SHARED_PREFIX)grpcpp_channelz$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpcpp_channelz.so.1
 	$(Q) ln -sf $(SHARED_PREFIX)grpcpp_channelz$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpcpp_channelz.so
 	$(Q) ln -sf $(SHARED_PREFIX)grpcpp_channelz$(SHARED_VERSION_CPP).$(SHARED_EXT_CPP) $(prefix)/lib/libgrpcpp_channelz.so
 endif
 endif
 ifneq ($(SYSTEM),MINGW32)
 ifneq ($(SYSTEM),MINGW32)
@@ -3131,7 +3131,7 @@ install-shared_csharp: shared_csharp strip-shared_csharp
 ifeq ($(SYSTEM),MINGW32)
 ifeq ($(SYSTEM),MINGW32)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP)-dll.a $(prefix)/lib/libgrpc_csharp_ext.a
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CSHARP)-dll.a $(prefix)/lib/libgrpc_csharp_ext.a
 else ifneq ($(SYSTEM),Darwin)
 else ifneq ($(SYSTEM),Darwin)
-	$(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(prefix)/lib/libgrpc_csharp_ext.so.7
+	$(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(prefix)/lib/libgrpc_csharp_ext.so.1
 	$(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(prefix)/lib/libgrpc_csharp_ext.so
 	$(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CSHARP).$(SHARED_EXT_CSHARP) $(prefix)/lib/libgrpc_csharp_ext.so
 endif
 endif
 ifneq ($(SYSTEM),MINGW32)
 ifneq ($(SYSTEM),MINGW32)
@@ -3721,12 +3721,12 @@ LIBGRPC_SRC = \
     src/core/ext/filters/client_channel/lb_policy.cc \
     src/core/ext/filters/client_channel/lb_policy.cc \
     src/core/ext/filters/client_channel/lb_policy_factory.cc \
     src/core/ext/filters/client_channel/lb_policy_factory.cc \
     src/core/ext/filters/client_channel/lb_policy_registry.cc \
     src/core/ext/filters/client_channel/lb_policy_registry.cc \
-    src/core/ext/filters/client_channel/method_params.cc \
     src/core/ext/filters/client_channel/parse_address.cc \
     src/core/ext/filters/client_channel/parse_address.cc \
     src/core/ext/filters/client_channel/proxy_mapper.cc \
     src/core/ext/filters/client_channel/proxy_mapper.cc \
     src/core/ext/filters/client_channel/proxy_mapper_registry.cc \
     src/core/ext/filters/client_channel/proxy_mapper_registry.cc \
     src/core/ext/filters/client_channel/resolver.cc \
     src/core/ext/filters/client_channel/resolver.cc \
     src/core/ext/filters/client_channel/resolver_registry.cc \
     src/core/ext/filters/client_channel/resolver_registry.cc \
+    src/core/ext/filters/client_channel/resolver_result_parsing.cc \
     src/core/ext/filters/client_channel/retry_throttle.cc \
     src/core/ext/filters/client_channel/retry_throttle.cc \
     src/core/ext/filters/client_channel/subchannel.cc \
     src/core/ext/filters/client_channel/subchannel.cc \
     src/core/ext/filters/client_channel/subchannel_index.cc \
     src/core/ext/filters/client_channel/subchannel_index.cc \
@@ -4067,12 +4067,12 @@ LIBGRPC_CRONET_SRC = \
     src/core/ext/filters/client_channel/lb_policy.cc \
     src/core/ext/filters/client_channel/lb_policy.cc \
     src/core/ext/filters/client_channel/lb_policy_factory.cc \
     src/core/ext/filters/client_channel/lb_policy_factory.cc \
     src/core/ext/filters/client_channel/lb_policy_registry.cc \
     src/core/ext/filters/client_channel/lb_policy_registry.cc \
-    src/core/ext/filters/client_channel/method_params.cc \
     src/core/ext/filters/client_channel/parse_address.cc \
     src/core/ext/filters/client_channel/parse_address.cc \
     src/core/ext/filters/client_channel/proxy_mapper.cc \
     src/core/ext/filters/client_channel/proxy_mapper.cc \
     src/core/ext/filters/client_channel/proxy_mapper_registry.cc \
     src/core/ext/filters/client_channel/proxy_mapper_registry.cc \
     src/core/ext/filters/client_channel/resolver.cc \
     src/core/ext/filters/client_channel/resolver.cc \
     src/core/ext/filters/client_channel/resolver_registry.cc \
     src/core/ext/filters/client_channel/resolver_registry.cc \
+    src/core/ext/filters/client_channel/resolver_result_parsing.cc \
     src/core/ext/filters/client_channel/retry_throttle.cc \
     src/core/ext/filters/client_channel/retry_throttle.cc \
     src/core/ext/filters/client_channel/subchannel.cc \
     src/core/ext/filters/client_channel/subchannel.cc \
     src/core/ext/filters/client_channel/subchannel_index.cc \
     src/core/ext/filters/client_channel/subchannel_index.cc \
@@ -4431,12 +4431,12 @@ LIBGRPC_TEST_UTIL_SRC = \
     src/core/ext/filters/client_channel/lb_policy.cc \
     src/core/ext/filters/client_channel/lb_policy.cc \
     src/core/ext/filters/client_channel/lb_policy_factory.cc \
     src/core/ext/filters/client_channel/lb_policy_factory.cc \
     src/core/ext/filters/client_channel/lb_policy_registry.cc \
     src/core/ext/filters/client_channel/lb_policy_registry.cc \
-    src/core/ext/filters/client_channel/method_params.cc \
     src/core/ext/filters/client_channel/parse_address.cc \
     src/core/ext/filters/client_channel/parse_address.cc \
     src/core/ext/filters/client_channel/proxy_mapper.cc \
     src/core/ext/filters/client_channel/proxy_mapper.cc \
     src/core/ext/filters/client_channel/proxy_mapper_registry.cc \
     src/core/ext/filters/client_channel/proxy_mapper_registry.cc \
     src/core/ext/filters/client_channel/resolver.cc \
     src/core/ext/filters/client_channel/resolver.cc \
     src/core/ext/filters/client_channel/resolver_registry.cc \
     src/core/ext/filters/client_channel/resolver_registry.cc \
+    src/core/ext/filters/client_channel/resolver_result_parsing.cc \
     src/core/ext/filters/client_channel/retry_throttle.cc \
     src/core/ext/filters/client_channel/retry_throttle.cc \
     src/core/ext/filters/client_channel/subchannel.cc \
     src/core/ext/filters/client_channel/subchannel.cc \
     src/core/ext/filters/client_channel/subchannel_index.cc \
     src/core/ext/filters/client_channel/subchannel_index.cc \
@@ -4737,12 +4737,12 @@ LIBGRPC_TEST_UTIL_UNSECURE_SRC = \
     src/core/ext/filters/client_channel/lb_policy.cc \
     src/core/ext/filters/client_channel/lb_policy.cc \
     src/core/ext/filters/client_channel/lb_policy_factory.cc \
     src/core/ext/filters/client_channel/lb_policy_factory.cc \
     src/core/ext/filters/client_channel/lb_policy_registry.cc \
     src/core/ext/filters/client_channel/lb_policy_registry.cc \
-    src/core/ext/filters/client_channel/method_params.cc \
     src/core/ext/filters/client_channel/parse_address.cc \
     src/core/ext/filters/client_channel/parse_address.cc \
     src/core/ext/filters/client_channel/proxy_mapper.cc \
     src/core/ext/filters/client_channel/proxy_mapper.cc \
     src/core/ext/filters/client_channel/proxy_mapper_registry.cc \
     src/core/ext/filters/client_channel/proxy_mapper_registry.cc \
     src/core/ext/filters/client_channel/resolver.cc \
     src/core/ext/filters/client_channel/resolver.cc \
     src/core/ext/filters/client_channel/resolver_registry.cc \
     src/core/ext/filters/client_channel/resolver_registry.cc \
+    src/core/ext/filters/client_channel/resolver_result_parsing.cc \
     src/core/ext/filters/client_channel/retry_throttle.cc \
     src/core/ext/filters/client_channel/retry_throttle.cc \
     src/core/ext/filters/client_channel/subchannel.cc \
     src/core/ext/filters/client_channel/subchannel.cc \
     src/core/ext/filters/client_channel/subchannel_index.cc \
     src/core/ext/filters/client_channel/subchannel_index.cc \
@@ -5044,12 +5044,12 @@ LIBGRPC_UNSECURE_SRC = \
     src/core/ext/filters/client_channel/lb_policy.cc \
     src/core/ext/filters/client_channel/lb_policy.cc \
     src/core/ext/filters/client_channel/lb_policy_factory.cc \
     src/core/ext/filters/client_channel/lb_policy_factory.cc \
     src/core/ext/filters/client_channel/lb_policy_registry.cc \
     src/core/ext/filters/client_channel/lb_policy_registry.cc \
-    src/core/ext/filters/client_channel/method_params.cc \
     src/core/ext/filters/client_channel/parse_address.cc \
     src/core/ext/filters/client_channel/parse_address.cc \
     src/core/ext/filters/client_channel/proxy_mapper.cc \
     src/core/ext/filters/client_channel/proxy_mapper.cc \
     src/core/ext/filters/client_channel/proxy_mapper_registry.cc \
     src/core/ext/filters/client_channel/proxy_mapper_registry.cc \
     src/core/ext/filters/client_channel/resolver.cc \
     src/core/ext/filters/client_channel/resolver.cc \
     src/core/ext/filters/client_channel/resolver_registry.cc \
     src/core/ext/filters/client_channel/resolver_registry.cc \
+    src/core/ext/filters/client_channel/resolver_result_parsing.cc \
     src/core/ext/filters/client_channel/retry_throttle.cc \
     src/core/ext/filters/client_channel/retry_throttle.cc \
     src/core/ext/filters/client_channel/subchannel.cc \
     src/core/ext/filters/client_channel/subchannel.cc \
     src/core/ext/filters/client_channel/subchannel_index.cc \
     src/core/ext/filters/client_channel/subchannel_index.cc \
@@ -5871,12 +5871,12 @@ LIBGRPC++_CRONET_SRC = \
     src/core/ext/filters/client_channel/lb_policy.cc \
     src/core/ext/filters/client_channel/lb_policy.cc \
     src/core/ext/filters/client_channel/lb_policy_factory.cc \
     src/core/ext/filters/client_channel/lb_policy_factory.cc \
     src/core/ext/filters/client_channel/lb_policy_registry.cc \
     src/core/ext/filters/client_channel/lb_policy_registry.cc \
-    src/core/ext/filters/client_channel/method_params.cc \
     src/core/ext/filters/client_channel/parse_address.cc \
     src/core/ext/filters/client_channel/parse_address.cc \
     src/core/ext/filters/client_channel/proxy_mapper.cc \
     src/core/ext/filters/client_channel/proxy_mapper.cc \
     src/core/ext/filters/client_channel/proxy_mapper_registry.cc \
     src/core/ext/filters/client_channel/proxy_mapper_registry.cc \
     src/core/ext/filters/client_channel/resolver.cc \
     src/core/ext/filters/client_channel/resolver.cc \
     src/core/ext/filters/client_channel/resolver_registry.cc \
     src/core/ext/filters/client_channel/resolver_registry.cc \
+    src/core/ext/filters/client_channel/resolver_result_parsing.cc \
     src/core/ext/filters/client_channel/retry_throttle.cc \
     src/core/ext/filters/client_channel/retry_throttle.cc \
     src/core/ext/filters/client_channel/subchannel.cc \
     src/core/ext/filters/client_channel/subchannel.cc \
     src/core/ext/filters/client_channel/subchannel_index.cc \
     src/core/ext/filters/client_channel/subchannel_index.cc \

+ 10 - 10
README.md

@@ -1,7 +1,7 @@
 gRPC - An RPC library and framework
 gRPC - An RPC library and framework
 ===================================
 ===================================
 
 
-gRPC is a modern, open source, high-performance remote procedure call (RPC) framework that can run anywhere. It enables client and server applications to communicate transparently, and makes it easier to build connected systems.
+gRPC is a modern, open source, high-performance remote procedure call (RPC) framework that can run anywhere. gRPC enables client and server applications to communicate transparently, and simplifies the building of connected systems.
 
 
 <table>
 <table>
   <tr>
   <tr>
@@ -18,10 +18,10 @@ gRPC is a modern, open source, high-performance remote procedure call (RPC) fram
 
 
 # To start using gRPC
 # To start using gRPC
 
 
-To maximize usability, gRPC supports the standard way of adding dependencies in your language of choice (if there is one).
-In most languages, the gRPC runtime comes in form of a package available in your language's package manager.
+To maximize usability, gRPC supports the standard method for adding dependencies to a user's chosen language (if there is one).
+In most languages, the gRPC runtime comes as a package available in a user's language package manager.
 
 
-For instructions on how to use the language-specific gRPC runtime in your project, please refer to these documents
+For instructions on how to use the language-specific gRPC runtime for a project, please refer to these documents
 
 
  * [C++](src/cpp): follow the instructions under the `src/cpp` directory
  * [C++](src/cpp): follow the instructions under the `src/cpp` directory
  * [C#](src/csharp): NuGet package `Grpc`
  * [C#](src/csharp): NuGet package `Grpc`
@@ -35,7 +35,7 @@ For instructions on how to use the language-specific gRPC runtime in your projec
  * [Ruby](src/ruby): `gem install grpc`
  * [Ruby](src/ruby): `gem install grpc`
  * [WebJS](https://github.com/grpc/grpc-web): follow the grpc-web instructions
  * [WebJS](https://github.com/grpc/grpc-web): follow the grpc-web instructions
 
 
-You can find per-language quickstart guides and tutorials in [Documentation section on grpc.io website](https://grpc.io/docs/). The code examples are available in the [examples](examples) directory.
+Per-language quickstart guides and tutorials can be found in the [documentation section on the grpc.io website](https://grpc.io/docs/). Code examples are available in the [examples](examples) directory.
 
 
 Precompiled bleeding-edge package builds of gRPC `master` branch's `HEAD` are uploaded daily to [packages.grpc.io](https://packages.grpc.io).
 Precompiled bleeding-edge package builds of gRPC `master` branch's `HEAD` are uploaded daily to [packages.grpc.io](https://packages.grpc.io).
 
 
@@ -43,9 +43,9 @@ Precompiled bleeding-edge package builds of gRPC `master` branch's `HEAD` are up
 
 
 Contributions are welcome!
 Contributions are welcome!
 
 
-Please read [How to contribute](CONTRIBUTING.md) which will guide you through the entire workflow of how to build the source code, how to run the tests and how to contribute your changes to
+Please read [How to contribute](CONTRIBUTING.md) which will guide you through the entire workflow of how to build the source code, how to run the tests, and how to contribute changes to
 the gRPC codebase.
 the gRPC codebase.
-The document also contains info on how the contributing process works and contains best practices for creating contributions.
+The "How to contribute" document also contains info on how the contribution process works and contains best practices for creating contributions.
 
 
 # Troubleshooting
 # Troubleshooting
 
 
@@ -53,7 +53,7 @@ Sometimes things go wrong. Please check out the [Troubleshooting guide](TROUBLES
 
 
 # Performance 
 # Performance 
 
 
-See [Performance dashboard](http://performance-dot-grpc-testing.appspot.com/explore?dashboard=5636470266134528) for the performance numbers for the latest released version.
+See the [Performance dashboard](http://performance-dot-grpc-testing.appspot.com/explore?dashboard=5636470266134528) for performance numbers of the latest released version.
 
 
 # Concepts
 # Concepts
 
 
@@ -61,9 +61,9 @@ See [gRPC Concepts](CONCEPTS.md)
 
 
 # About This Repository
 # About This Repository
 
 
-This repository contains source code for gRPC libraries for multiple languages written on top of shared C core library [src/core](src/core).
+This repository contains source code for gRPC libraries implemented in multiple languages written on top of a shared C core library [src/core](src/core).
 
 
-Libraries in different languages may be in different states of development. We are seeking contributions for all of these libraries.
+Libraries in different languages may be in various states of development. We are seeking contributions for all of these libraries:
 
 
 | Language                | Source                              |
 | Language                | Source                              |
 |-------------------------|-------------------------------------|
 |-------------------------|-------------------------------------|

+ 4 - 4
build.yaml

@@ -13,8 +13,8 @@ settings:
   '#09': Per-language overrides are possible with (eg) ruby_version tag here
   '#09': Per-language overrides are possible with (eg) ruby_version tag here
   '#10': See the expand_version.py for all the quirks here
   '#10': See the expand_version.py for all the quirks here
   core_version: 7.0.0-dev
   core_version: 7.0.0-dev
-  g_stands_for: gizmo
-  version: 1.17.0-dev
+  g_stands_for: goose
+  version: 1.18.0-dev
 filegroups:
 filegroups:
 - name: alts_proto
 - name: alts_proto
   headers:
   headers:
@@ -580,13 +580,13 @@ filegroups:
   - src/core/ext/filters/client_channel/lb_policy.h
   - src/core/ext/filters/client_channel/lb_policy.h
   - src/core/ext/filters/client_channel/lb_policy_factory.h
   - src/core/ext/filters/client_channel/lb_policy_factory.h
   - src/core/ext/filters/client_channel/lb_policy_registry.h
   - src/core/ext/filters/client_channel/lb_policy_registry.h
-  - src/core/ext/filters/client_channel/method_params.h
   - src/core/ext/filters/client_channel/parse_address.h
   - src/core/ext/filters/client_channel/parse_address.h
   - src/core/ext/filters/client_channel/proxy_mapper.h
   - src/core/ext/filters/client_channel/proxy_mapper.h
   - src/core/ext/filters/client_channel/proxy_mapper_registry.h
   - src/core/ext/filters/client_channel/proxy_mapper_registry.h
   - src/core/ext/filters/client_channel/resolver.h
   - src/core/ext/filters/client_channel/resolver.h
   - src/core/ext/filters/client_channel/resolver_factory.h
   - src/core/ext/filters/client_channel/resolver_factory.h
   - src/core/ext/filters/client_channel/resolver_registry.h
   - src/core/ext/filters/client_channel/resolver_registry.h
+  - src/core/ext/filters/client_channel/resolver_result_parsing.h
   - src/core/ext/filters/client_channel/retry_throttle.h
   - src/core/ext/filters/client_channel/retry_throttle.h
   - src/core/ext/filters/client_channel/subchannel.h
   - src/core/ext/filters/client_channel/subchannel.h
   - src/core/ext/filters/client_channel/subchannel_index.h
   - src/core/ext/filters/client_channel/subchannel_index.h
@@ -604,12 +604,12 @@ filegroups:
   - src/core/ext/filters/client_channel/lb_policy.cc
   - src/core/ext/filters/client_channel/lb_policy.cc
   - src/core/ext/filters/client_channel/lb_policy_factory.cc
   - src/core/ext/filters/client_channel/lb_policy_factory.cc
   - src/core/ext/filters/client_channel/lb_policy_registry.cc
   - src/core/ext/filters/client_channel/lb_policy_registry.cc
-  - src/core/ext/filters/client_channel/method_params.cc
   - src/core/ext/filters/client_channel/parse_address.cc
   - src/core/ext/filters/client_channel/parse_address.cc
   - src/core/ext/filters/client_channel/proxy_mapper.cc
   - src/core/ext/filters/client_channel/proxy_mapper.cc
   - src/core/ext/filters/client_channel/proxy_mapper_registry.cc
   - src/core/ext/filters/client_channel/proxy_mapper_registry.cc
   - src/core/ext/filters/client_channel/resolver.cc
   - src/core/ext/filters/client_channel/resolver.cc
   - src/core/ext/filters/client_channel/resolver_registry.cc
   - src/core/ext/filters/client_channel/resolver_registry.cc
+  - src/core/ext/filters/client_channel/resolver_result_parsing.cc
   - src/core/ext/filters/client_channel/retry_throttle.cc
   - src/core/ext/filters/client_channel/retry_throttle.cc
   - src/core/ext/filters/client_channel/subchannel.cc
   - src/core/ext/filters/client_channel/subchannel.cc
   - src/core/ext/filters/client_channel/subchannel_index.cc
   - src/core/ext/filters/client_channel/subchannel_index.cc

+ 3 - 2
config.m4

@@ -350,12 +350,12 @@ if test "$PHP_GRPC" != "no"; then
     src/core/ext/filters/client_channel/lb_policy.cc \
     src/core/ext/filters/client_channel/lb_policy.cc \
     src/core/ext/filters/client_channel/lb_policy_factory.cc \
     src/core/ext/filters/client_channel/lb_policy_factory.cc \
     src/core/ext/filters/client_channel/lb_policy_registry.cc \
     src/core/ext/filters/client_channel/lb_policy_registry.cc \
-    src/core/ext/filters/client_channel/method_params.cc \
     src/core/ext/filters/client_channel/parse_address.cc \
     src/core/ext/filters/client_channel/parse_address.cc \
     src/core/ext/filters/client_channel/proxy_mapper.cc \
     src/core/ext/filters/client_channel/proxy_mapper.cc \
     src/core/ext/filters/client_channel/proxy_mapper_registry.cc \
     src/core/ext/filters/client_channel/proxy_mapper_registry.cc \
     src/core/ext/filters/client_channel/resolver.cc \
     src/core/ext/filters/client_channel/resolver.cc \
     src/core/ext/filters/client_channel/resolver_registry.cc \
     src/core/ext/filters/client_channel/resolver_registry.cc \
+    src/core/ext/filters/client_channel/resolver_result_parsing.cc \
     src/core/ext/filters/client_channel/retry_throttle.cc \
     src/core/ext/filters/client_channel/retry_throttle.cc \
     src/core/ext/filters/client_channel/subchannel.cc \
     src/core/ext/filters/client_channel/subchannel.cc \
     src/core/ext/filters/client_channel/subchannel_index.cc \
     src/core/ext/filters/client_channel/subchannel_index.cc \
@@ -665,7 +665,8 @@ if test "$PHP_GRPC" != "no"; then
     third_party/boringssl/third_party/fiat/curve25519.c \
     third_party/boringssl/third_party/fiat/curve25519.c \
     , $ext_shared, , -fvisibility=hidden \
     , $ext_shared, , -fvisibility=hidden \
     -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN \
     -DOPENSSL_NO_ASM -D_GNU_SOURCE -DWIN32_LEAN_AND_MEAN \
-    -D_HAS_EXCEPTIONS=0 -DNOMINMAX -DGRPC_ARES=0)
+    -D_HAS_EXCEPTIONS=0 -DNOMINMAX -DGRPC_ARES=0 \
+    -DGRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK=1)
 
 
   PHP_ADD_BUILD_DIR($ext_builddir/src/php/ext/grpc)
   PHP_ADD_BUILD_DIR($ext_builddir/src/php/ext/grpc)
 
 

+ 1 - 1
config.w32

@@ -325,12 +325,12 @@ if (PHP_GRPC != "no") {
     "src\\core\\ext\\filters\\client_channel\\lb_policy.cc " +
     "src\\core\\ext\\filters\\client_channel\\lb_policy.cc " +
     "src\\core\\ext\\filters\\client_channel\\lb_policy_factory.cc " +
     "src\\core\\ext\\filters\\client_channel\\lb_policy_factory.cc " +
     "src\\core\\ext\\filters\\client_channel\\lb_policy_registry.cc " +
     "src\\core\\ext\\filters\\client_channel\\lb_policy_registry.cc " +
-    "src\\core\\ext\\filters\\client_channel\\method_params.cc " +
     "src\\core\\ext\\filters\\client_channel\\parse_address.cc " +
     "src\\core\\ext\\filters\\client_channel\\parse_address.cc " +
     "src\\core\\ext\\filters\\client_channel\\proxy_mapper.cc " +
     "src\\core\\ext\\filters\\client_channel\\proxy_mapper.cc " +
     "src\\core\\ext\\filters\\client_channel\\proxy_mapper_registry.cc " +
     "src\\core\\ext\\filters\\client_channel\\proxy_mapper_registry.cc " +
     "src\\core\\ext\\filters\\client_channel\\resolver.cc " +
     "src\\core\\ext\\filters\\client_channel\\resolver.cc " +
     "src\\core\\ext\\filters\\client_channel\\resolver_registry.cc " +
     "src\\core\\ext\\filters\\client_channel\\resolver_registry.cc " +
+    "src\\core\\ext\\filters\\client_channel\\resolver_result_parsing.cc " +
     "src\\core\\ext\\filters\\client_channel\\retry_throttle.cc " +
     "src\\core\\ext\\filters\\client_channel\\retry_throttle.cc " +
     "src\\core\\ext\\filters\\client_channel\\subchannel.cc " +
     "src\\core\\ext\\filters\\client_channel\\subchannel.cc " +
     "src\\core\\ext\\filters\\client_channel\\subchannel_index.cc " +
     "src\\core\\ext\\filters\\client_channel\\subchannel_index.cc " +

+ 2 - 1
doc/g_stands_for.md

@@ -16,4 +16,5 @@
 - 1.14 'g' stands for ['gladiolus'](https://github.com/grpc/grpc/tree/v1.14.x)
 - 1.14 'g' stands for ['gladiolus'](https://github.com/grpc/grpc/tree/v1.14.x)
 - 1.15 'g' stands for ['glider'](https://github.com/grpc/grpc/tree/v1.15.x)
 - 1.15 'g' stands for ['glider'](https://github.com/grpc/grpc/tree/v1.15.x)
 - 1.16 'g' stands for ['gao'](https://github.com/grpc/grpc/tree/v1.16.x)
 - 1.16 'g' stands for ['gao'](https://github.com/grpc/grpc/tree/v1.16.x)
-- 1.17 'g' stands for ['gizmo'](https://github.com/grpc/grpc/tree/master)
+- 1.17 'g' stands for ['gizmo'](https://github.com/grpc/grpc/tree/v1.17.x)
+- 1.18 'g' stands for ['goose'](https://github.com/grpc/grpc/tree/master)

+ 4 - 4
gRPC-C++.podspec

@@ -23,15 +23,15 @@
 Pod::Spec.new do |s|
 Pod::Spec.new do |s|
   s.name     = 'gRPC-C++'
   s.name     = 'gRPC-C++'
   # TODO (mxyan): use version that match gRPC version when pod is stabilized
   # TODO (mxyan): use version that match gRPC version when pod is stabilized
-  # version = '1.17.0-dev'
-  version = '0.0.3'
+  # version = '1.18.0-dev'
+  version = '0.0.4'
   s.version  = version
   s.version  = version
   s.summary  = 'gRPC C++ library'
   s.summary  = 'gRPC C++ library'
   s.homepage = 'https://grpc.io'
   s.homepage = 'https://grpc.io'
   s.license  = 'Apache License, Version 2.0'
   s.license  = 'Apache License, Version 2.0'
   s.authors  = { 'The gRPC contributors' => 'grpc-packages@google.com' }
   s.authors  = { 'The gRPC contributors' => 'grpc-packages@google.com' }
 
 
-  grpc_version = '1.17.0-dev'
+  grpc_version = '1.18.0-dev'
 
 
   s.source = {
   s.source = {
     :git => 'https://github.com/grpc/grpc.git',
     :git => 'https://github.com/grpc/grpc.git',
@@ -348,13 +348,13 @@ Pod::Spec.new do |s|
                       'src/core/ext/filters/client_channel/lb_policy.h',
                       'src/core/ext/filters/client_channel/lb_policy.h',
                       'src/core/ext/filters/client_channel/lb_policy_factory.h',
                       'src/core/ext/filters/client_channel/lb_policy_factory.h',
                       'src/core/ext/filters/client_channel/lb_policy_registry.h',
                       'src/core/ext/filters/client_channel/lb_policy_registry.h',
-                      'src/core/ext/filters/client_channel/method_params.h',
                       'src/core/ext/filters/client_channel/parse_address.h',
                       'src/core/ext/filters/client_channel/parse_address.h',
                       'src/core/ext/filters/client_channel/proxy_mapper.h',
                       'src/core/ext/filters/client_channel/proxy_mapper.h',
                       'src/core/ext/filters/client_channel/proxy_mapper_registry.h',
                       'src/core/ext/filters/client_channel/proxy_mapper_registry.h',
                       'src/core/ext/filters/client_channel/resolver.h',
                       'src/core/ext/filters/client_channel/resolver.h',
                       'src/core/ext/filters/client_channel/resolver_factory.h',
                       'src/core/ext/filters/client_channel/resolver_factory.h',
                       'src/core/ext/filters/client_channel/resolver_registry.h',
                       'src/core/ext/filters/client_channel/resolver_registry.h',
+                      'src/core/ext/filters/client_channel/resolver_result_parsing.h',
                       'src/core/ext/filters/client_channel/retry_throttle.h',
                       'src/core/ext/filters/client_channel/retry_throttle.h',
                       'src/core/ext/filters/client_channel/subchannel.h',
                       'src/core/ext/filters/client_channel/subchannel.h',
                       'src/core/ext/filters/client_channel/subchannel_index.h',
                       'src/core/ext/filters/client_channel/subchannel_index.h',

+ 4 - 4
gRPC-Core.podspec

@@ -22,7 +22,7 @@
 
 
 Pod::Spec.new do |s|
 Pod::Spec.new do |s|
   s.name     = 'gRPC-Core'
   s.name     = 'gRPC-Core'
-  version = '1.17.0-dev'
+  version = '1.18.0-dev'
   s.version  = version
   s.version  = version
   s.summary  = 'Core cross-platform gRPC library, written in C'
   s.summary  = 'Core cross-platform gRPC library, written in C'
   s.homepage = 'https://grpc.io'
   s.homepage = 'https://grpc.io'
@@ -346,13 +346,13 @@ Pod::Spec.new do |s|
                       'src/core/ext/filters/client_channel/lb_policy.h',
                       'src/core/ext/filters/client_channel/lb_policy.h',
                       'src/core/ext/filters/client_channel/lb_policy_factory.h',
                       'src/core/ext/filters/client_channel/lb_policy_factory.h',
                       'src/core/ext/filters/client_channel/lb_policy_registry.h',
                       'src/core/ext/filters/client_channel/lb_policy_registry.h',
-                      'src/core/ext/filters/client_channel/method_params.h',
                       'src/core/ext/filters/client_channel/parse_address.h',
                       'src/core/ext/filters/client_channel/parse_address.h',
                       'src/core/ext/filters/client_channel/proxy_mapper.h',
                       'src/core/ext/filters/client_channel/proxy_mapper.h',
                       'src/core/ext/filters/client_channel/proxy_mapper_registry.h',
                       'src/core/ext/filters/client_channel/proxy_mapper_registry.h',
                       'src/core/ext/filters/client_channel/resolver.h',
                       'src/core/ext/filters/client_channel/resolver.h',
                       'src/core/ext/filters/client_channel/resolver_factory.h',
                       'src/core/ext/filters/client_channel/resolver_factory.h',
                       'src/core/ext/filters/client_channel/resolver_registry.h',
                       'src/core/ext/filters/client_channel/resolver_registry.h',
+                      'src/core/ext/filters/client_channel/resolver_result_parsing.h',
                       'src/core/ext/filters/client_channel/retry_throttle.h',
                       'src/core/ext/filters/client_channel/retry_throttle.h',
                       'src/core/ext/filters/client_channel/subchannel.h',
                       'src/core/ext/filters/client_channel/subchannel.h',
                       'src/core/ext/filters/client_channel/subchannel_index.h',
                       'src/core/ext/filters/client_channel/subchannel_index.h',
@@ -787,12 +787,12 @@ Pod::Spec.new do |s|
                       'src/core/ext/filters/client_channel/lb_policy.cc',
                       'src/core/ext/filters/client_channel/lb_policy.cc',
                       'src/core/ext/filters/client_channel/lb_policy_factory.cc',
                       'src/core/ext/filters/client_channel/lb_policy_factory.cc',
                       'src/core/ext/filters/client_channel/lb_policy_registry.cc',
                       'src/core/ext/filters/client_channel/lb_policy_registry.cc',
-                      'src/core/ext/filters/client_channel/method_params.cc',
                       'src/core/ext/filters/client_channel/parse_address.cc',
                       'src/core/ext/filters/client_channel/parse_address.cc',
                       'src/core/ext/filters/client_channel/proxy_mapper.cc',
                       'src/core/ext/filters/client_channel/proxy_mapper.cc',
                       'src/core/ext/filters/client_channel/proxy_mapper_registry.cc',
                       'src/core/ext/filters/client_channel/proxy_mapper_registry.cc',
                       'src/core/ext/filters/client_channel/resolver.cc',
                       'src/core/ext/filters/client_channel/resolver.cc',
                       'src/core/ext/filters/client_channel/resolver_registry.cc',
                       'src/core/ext/filters/client_channel/resolver_registry.cc',
+                      'src/core/ext/filters/client_channel/resolver_result_parsing.cc',
                       'src/core/ext/filters/client_channel/retry_throttle.cc',
                       'src/core/ext/filters/client_channel/retry_throttle.cc',
                       'src/core/ext/filters/client_channel/subchannel.cc',
                       'src/core/ext/filters/client_channel/subchannel.cc',
                       'src/core/ext/filters/client_channel/subchannel_index.cc',
                       'src/core/ext/filters/client_channel/subchannel_index.cc',
@@ -965,13 +965,13 @@ Pod::Spec.new do |s|
                               'src/core/ext/filters/client_channel/lb_policy.h',
                               'src/core/ext/filters/client_channel/lb_policy.h',
                               'src/core/ext/filters/client_channel/lb_policy_factory.h',
                               'src/core/ext/filters/client_channel/lb_policy_factory.h',
                               'src/core/ext/filters/client_channel/lb_policy_registry.h',
                               'src/core/ext/filters/client_channel/lb_policy_registry.h',
-                              'src/core/ext/filters/client_channel/method_params.h',
                               'src/core/ext/filters/client_channel/parse_address.h',
                               'src/core/ext/filters/client_channel/parse_address.h',
                               'src/core/ext/filters/client_channel/proxy_mapper.h',
                               'src/core/ext/filters/client_channel/proxy_mapper.h',
                               'src/core/ext/filters/client_channel/proxy_mapper_registry.h',
                               'src/core/ext/filters/client_channel/proxy_mapper_registry.h',
                               'src/core/ext/filters/client_channel/resolver.h',
                               'src/core/ext/filters/client_channel/resolver.h',
                               'src/core/ext/filters/client_channel/resolver_factory.h',
                               'src/core/ext/filters/client_channel/resolver_factory.h',
                               'src/core/ext/filters/client_channel/resolver_registry.h',
                               'src/core/ext/filters/client_channel/resolver_registry.h',
+                              'src/core/ext/filters/client_channel/resolver_result_parsing.h',
                               'src/core/ext/filters/client_channel/retry_throttle.h',
                               'src/core/ext/filters/client_channel/retry_throttle.h',
                               'src/core/ext/filters/client_channel/subchannel.h',
                               'src/core/ext/filters/client_channel/subchannel.h',
                               'src/core/ext/filters/client_channel/subchannel_index.h',
                               'src/core/ext/filters/client_channel/subchannel_index.h',

+ 1 - 1
gRPC-ProtoRPC.podspec

@@ -21,7 +21,7 @@
 
 
 Pod::Spec.new do |s|
 Pod::Spec.new do |s|
   s.name     = 'gRPC-ProtoRPC'
   s.name     = 'gRPC-ProtoRPC'
-  version = '1.17.0-dev'
+  version = '1.18.0-dev'
   s.version  = version
   s.version  = version
   s.summary  = 'RPC library for Protocol Buffers, based on gRPC'
   s.summary  = 'RPC library for Protocol Buffers, based on gRPC'
   s.homepage = 'https://grpc.io'
   s.homepage = 'https://grpc.io'

+ 1 - 1
gRPC-RxLibrary.podspec

@@ -21,7 +21,7 @@
 
 
 Pod::Spec.new do |s|
 Pod::Spec.new do |s|
   s.name     = 'gRPC-RxLibrary'
   s.name     = 'gRPC-RxLibrary'
-  version = '1.17.0-dev'
+  version = '1.18.0-dev'
   s.version  = version
   s.version  = version
   s.summary  = 'Reactive Extensions library for iOS/OSX.'
   s.summary  = 'Reactive Extensions library for iOS/OSX.'
   s.homepage = 'https://grpc.io'
   s.homepage = 'https://grpc.io'

+ 1 - 1
gRPC.podspec

@@ -20,7 +20,7 @@
 
 
 Pod::Spec.new do |s|
 Pod::Spec.new do |s|
   s.name     = 'gRPC'
   s.name     = 'gRPC'
-  version = '1.17.0-dev'
+  version = '1.18.0-dev'
   s.version  = version
   s.version  = version
   s.summary  = 'gRPC client library for iOS/OSX'
   s.summary  = 'gRPC client library for iOS/OSX'
   s.homepage = 'https://grpc.io'
   s.homepage = 'https://grpc.io'

+ 2 - 2
grpc.gemspec

@@ -282,13 +282,13 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/ext/filters/client_channel/lb_policy.h )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy.h )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy_factory.h )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy_factory.h )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy_registry.h )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy_registry.h )
-  s.files += %w( src/core/ext/filters/client_channel/method_params.h )
   s.files += %w( src/core/ext/filters/client_channel/parse_address.h )
   s.files += %w( src/core/ext/filters/client_channel/parse_address.h )
   s.files += %w( src/core/ext/filters/client_channel/proxy_mapper.h )
   s.files += %w( src/core/ext/filters/client_channel/proxy_mapper.h )
   s.files += %w( src/core/ext/filters/client_channel/proxy_mapper_registry.h )
   s.files += %w( src/core/ext/filters/client_channel/proxy_mapper_registry.h )
   s.files += %w( src/core/ext/filters/client_channel/resolver.h )
   s.files += %w( src/core/ext/filters/client_channel/resolver.h )
   s.files += %w( src/core/ext/filters/client_channel/resolver_factory.h )
   s.files += %w( src/core/ext/filters/client_channel/resolver_factory.h )
   s.files += %w( src/core/ext/filters/client_channel/resolver_registry.h )
   s.files += %w( src/core/ext/filters/client_channel/resolver_registry.h )
+  s.files += %w( src/core/ext/filters/client_channel/resolver_result_parsing.h )
   s.files += %w( src/core/ext/filters/client_channel/retry_throttle.h )
   s.files += %w( src/core/ext/filters/client_channel/retry_throttle.h )
   s.files += %w( src/core/ext/filters/client_channel/subchannel.h )
   s.files += %w( src/core/ext/filters/client_channel/subchannel.h )
   s.files += %w( src/core/ext/filters/client_channel/subchannel_index.h )
   s.files += %w( src/core/ext/filters/client_channel/subchannel_index.h )
@@ -726,12 +726,12 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/ext/filters/client_channel/lb_policy.cc )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy.cc )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy_factory.cc )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy_factory.cc )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy_registry.cc )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy_registry.cc )
-  s.files += %w( src/core/ext/filters/client_channel/method_params.cc )
   s.files += %w( src/core/ext/filters/client_channel/parse_address.cc )
   s.files += %w( src/core/ext/filters/client_channel/parse_address.cc )
   s.files += %w( src/core/ext/filters/client_channel/proxy_mapper.cc )
   s.files += %w( src/core/ext/filters/client_channel/proxy_mapper.cc )
   s.files += %w( src/core/ext/filters/client_channel/proxy_mapper_registry.cc )
   s.files += %w( src/core/ext/filters/client_channel/proxy_mapper_registry.cc )
   s.files += %w( src/core/ext/filters/client_channel/resolver.cc )
   s.files += %w( src/core/ext/filters/client_channel/resolver.cc )
   s.files += %w( src/core/ext/filters/client_channel/resolver_registry.cc )
   s.files += %w( src/core/ext/filters/client_channel/resolver_registry.cc )
+  s.files += %w( src/core/ext/filters/client_channel/resolver_result_parsing.cc )
   s.files += %w( src/core/ext/filters/client_channel/retry_throttle.cc )
   s.files += %w( src/core/ext/filters/client_channel/retry_throttle.cc )
   s.files += %w( src/core/ext/filters/client_channel/subchannel.cc )
   s.files += %w( src/core/ext/filters/client_channel/subchannel.cc )
   s.files += %w( src/core/ext/filters/client_channel/subchannel_index.cc )
   s.files += %w( src/core/ext/filters/client_channel/subchannel_index.cc )

+ 4 - 4
grpc.gyp

@@ -542,12 +542,12 @@
         'src/core/ext/filters/client_channel/lb_policy.cc',
         'src/core/ext/filters/client_channel/lb_policy.cc',
         'src/core/ext/filters/client_channel/lb_policy_factory.cc',
         'src/core/ext/filters/client_channel/lb_policy_factory.cc',
         'src/core/ext/filters/client_channel/lb_policy_registry.cc',
         'src/core/ext/filters/client_channel/lb_policy_registry.cc',
-        'src/core/ext/filters/client_channel/method_params.cc',
         'src/core/ext/filters/client_channel/parse_address.cc',
         'src/core/ext/filters/client_channel/parse_address.cc',
         'src/core/ext/filters/client_channel/proxy_mapper.cc',
         'src/core/ext/filters/client_channel/proxy_mapper.cc',
         'src/core/ext/filters/client_channel/proxy_mapper_registry.cc',
         'src/core/ext/filters/client_channel/proxy_mapper_registry.cc',
         'src/core/ext/filters/client_channel/resolver.cc',
         'src/core/ext/filters/client_channel/resolver.cc',
         'src/core/ext/filters/client_channel/resolver_registry.cc',
         'src/core/ext/filters/client_channel/resolver_registry.cc',
+        'src/core/ext/filters/client_channel/resolver_result_parsing.cc',
         'src/core/ext/filters/client_channel/retry_throttle.cc',
         'src/core/ext/filters/client_channel/retry_throttle.cc',
         'src/core/ext/filters/client_channel/subchannel.cc',
         'src/core/ext/filters/client_channel/subchannel.cc',
         'src/core/ext/filters/client_channel/subchannel_index.cc',
         'src/core/ext/filters/client_channel/subchannel_index.cc',
@@ -801,12 +801,12 @@
         'src/core/ext/filters/client_channel/lb_policy.cc',
         'src/core/ext/filters/client_channel/lb_policy.cc',
         'src/core/ext/filters/client_channel/lb_policy_factory.cc',
         'src/core/ext/filters/client_channel/lb_policy_factory.cc',
         'src/core/ext/filters/client_channel/lb_policy_registry.cc',
         'src/core/ext/filters/client_channel/lb_policy_registry.cc',
-        'src/core/ext/filters/client_channel/method_params.cc',
         'src/core/ext/filters/client_channel/parse_address.cc',
         'src/core/ext/filters/client_channel/parse_address.cc',
         'src/core/ext/filters/client_channel/proxy_mapper.cc',
         'src/core/ext/filters/client_channel/proxy_mapper.cc',
         'src/core/ext/filters/client_channel/proxy_mapper_registry.cc',
         'src/core/ext/filters/client_channel/proxy_mapper_registry.cc',
         'src/core/ext/filters/client_channel/resolver.cc',
         'src/core/ext/filters/client_channel/resolver.cc',
         'src/core/ext/filters/client_channel/resolver_registry.cc',
         'src/core/ext/filters/client_channel/resolver_registry.cc',
+        'src/core/ext/filters/client_channel/resolver_result_parsing.cc',
         'src/core/ext/filters/client_channel/retry_throttle.cc',
         'src/core/ext/filters/client_channel/retry_throttle.cc',
         'src/core/ext/filters/client_channel/subchannel.cc',
         'src/core/ext/filters/client_channel/subchannel.cc',
         'src/core/ext/filters/client_channel/subchannel_index.cc',
         'src/core/ext/filters/client_channel/subchannel_index.cc',
@@ -1041,12 +1041,12 @@
         'src/core/ext/filters/client_channel/lb_policy.cc',
         'src/core/ext/filters/client_channel/lb_policy.cc',
         'src/core/ext/filters/client_channel/lb_policy_factory.cc',
         'src/core/ext/filters/client_channel/lb_policy_factory.cc',
         'src/core/ext/filters/client_channel/lb_policy_registry.cc',
         'src/core/ext/filters/client_channel/lb_policy_registry.cc',
-        'src/core/ext/filters/client_channel/method_params.cc',
         'src/core/ext/filters/client_channel/parse_address.cc',
         'src/core/ext/filters/client_channel/parse_address.cc',
         'src/core/ext/filters/client_channel/proxy_mapper.cc',
         'src/core/ext/filters/client_channel/proxy_mapper.cc',
         'src/core/ext/filters/client_channel/proxy_mapper_registry.cc',
         'src/core/ext/filters/client_channel/proxy_mapper_registry.cc',
         'src/core/ext/filters/client_channel/resolver.cc',
         'src/core/ext/filters/client_channel/resolver.cc',
         'src/core/ext/filters/client_channel/resolver_registry.cc',
         'src/core/ext/filters/client_channel/resolver_registry.cc',
+        'src/core/ext/filters/client_channel/resolver_result_parsing.cc',
         'src/core/ext/filters/client_channel/retry_throttle.cc',
         'src/core/ext/filters/client_channel/retry_throttle.cc',
         'src/core/ext/filters/client_channel/subchannel.cc',
         'src/core/ext/filters/client_channel/subchannel.cc',
         'src/core/ext/filters/client_channel/subchannel_index.cc',
         'src/core/ext/filters/client_channel/subchannel_index.cc',
@@ -1294,12 +1294,12 @@
         'src/core/ext/filters/client_channel/lb_policy.cc',
         'src/core/ext/filters/client_channel/lb_policy.cc',
         'src/core/ext/filters/client_channel/lb_policy_factory.cc',
         'src/core/ext/filters/client_channel/lb_policy_factory.cc',
         'src/core/ext/filters/client_channel/lb_policy_registry.cc',
         'src/core/ext/filters/client_channel/lb_policy_registry.cc',
-        'src/core/ext/filters/client_channel/method_params.cc',
         'src/core/ext/filters/client_channel/parse_address.cc',
         'src/core/ext/filters/client_channel/parse_address.cc',
         'src/core/ext/filters/client_channel/proxy_mapper.cc',
         'src/core/ext/filters/client_channel/proxy_mapper.cc',
         'src/core/ext/filters/client_channel/proxy_mapper_registry.cc',
         'src/core/ext/filters/client_channel/proxy_mapper_registry.cc',
         'src/core/ext/filters/client_channel/resolver.cc',
         'src/core/ext/filters/client_channel/resolver.cc',
         'src/core/ext/filters/client_channel/resolver_registry.cc',
         'src/core/ext/filters/client_channel/resolver_registry.cc',
+        'src/core/ext/filters/client_channel/resolver_result_parsing.cc',
         'src/core/ext/filters/client_channel/retry_throttle.cc',
         'src/core/ext/filters/client_channel/retry_throttle.cc',
         'src/core/ext/filters/client_channel/subchannel.cc',
         'src/core/ext/filters/client_channel/subchannel.cc',
         'src/core/ext/filters/client_channel/subchannel_index.cc',
         'src/core/ext/filters/client_channel/subchannel_index.cc',

+ 4 - 4
include/grpcpp/channel.h

@@ -65,13 +65,13 @@ class Channel final : public ChannelInterface,
   friend void experimental::ChannelResetConnectionBackoff(Channel* channel);
   friend void experimental::ChannelResetConnectionBackoff(Channel* channel);
   friend std::shared_ptr<Channel> CreateChannelInternal(
   friend std::shared_ptr<Channel> CreateChannelInternal(
       const grpc::string& host, grpc_channel* c_channel,
       const grpc::string& host, grpc_channel* c_channel,
-      std::unique_ptr<std::vector<
-          std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>>
+      std::vector<
+          std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
           interceptor_creators);
           interceptor_creators);
   friend class internal::InterceptedChannel;
   friend class internal::InterceptedChannel;
   Channel(const grpc::string& host, grpc_channel* c_channel,
   Channel(const grpc::string& host, grpc_channel* c_channel,
-          std::unique_ptr<std::vector<
-              std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>>
+          std::vector<
+              std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
               interceptor_creators);
               interceptor_creators);
 
 
   internal::Call CreateCall(const internal::RpcMethod& method,
   internal::Call CreateCall(const internal::RpcMethod& method,

+ 2 - 2
include/grpcpp/create_channel.h

@@ -70,8 +70,8 @@ std::shared_ptr<Channel> CreateCustomChannelWithInterceptors(
     const grpc::string& target,
     const grpc::string& target,
     const std::shared_ptr<ChannelCredentials>& creds,
     const std::shared_ptr<ChannelCredentials>& creds,
     const ChannelArguments& args,
     const ChannelArguments& args,
-    std::unique_ptr<std::vector<
-        std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>>
+    std::vector<
+        std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
         interceptor_creators);
         interceptor_creators);
 }  // namespace experimental
 }  // namespace experimental
 }  // namespace grpc
 }  // namespace grpc

+ 1 - 2
include/grpcpp/impl/codegen/completion_queue.h

@@ -307,8 +307,7 @@ class CompletionQueue : private GrpcLibraryCodegen {
       void* ignored = tag;
       void* ignored = tag;
       if (tag->FinalizeResult(&ignored, &ok)) {
       if (tag->FinalizeResult(&ignored, &ok)) {
         GPR_CODEGEN_ASSERT(ignored == tag);
         GPR_CODEGEN_ASSERT(ignored == tag);
-        // Ignore mutations by FinalizeResult: Pluck returns the C API status
-        return ev.success != 0;
+        return ok;
       }
       }
     }
     }
   }
   }

+ 6 - 6
include/grpcpp/security/credentials.h

@@ -46,8 +46,8 @@ std::shared_ptr<Channel> CreateCustomChannelWithInterceptors(
     const grpc::string& target,
     const grpc::string& target,
     const std::shared_ptr<ChannelCredentials>& creds,
     const std::shared_ptr<ChannelCredentials>& creds,
     const ChannelArguments& args,
     const ChannelArguments& args,
-    std::unique_ptr<std::vector<
-        std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>>
+    std::vector<
+        std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
         interceptor_creators);
         interceptor_creators);
 }  // namespace experimental
 }  // namespace experimental
 
 
@@ -80,8 +80,8 @@ class ChannelCredentials : private GrpcLibraryCodegen {
       const grpc::string& target,
       const grpc::string& target,
       const std::shared_ptr<ChannelCredentials>& creds,
       const std::shared_ptr<ChannelCredentials>& creds,
       const ChannelArguments& args,
       const ChannelArguments& args,
-      std::unique_ptr<std::vector<
-          std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>>
+      std::vector<
+          std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
           interceptor_creators);
           interceptor_creators);
 
 
   virtual std::shared_ptr<Channel> CreateChannel(
   virtual std::shared_ptr<Channel> CreateChannel(
@@ -91,8 +91,8 @@ class ChannelCredentials : private GrpcLibraryCodegen {
   // implemented as a virtual function so that it does not break API.
   // implemented as a virtual function so that it does not break API.
   virtual std::shared_ptr<Channel> CreateChannelWithInterceptors(
   virtual std::shared_ptr<Channel> CreateChannelWithInterceptors(
       const grpc::string& target, const ChannelArguments& args,
       const grpc::string& target, const ChannelArguments& args,
-      std::unique_ptr<std::vector<
-          std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>>
+      std::vector<
+          std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
           interceptor_creators) {
           interceptor_creators) {
     return nullptr;
     return nullptr;
   };
   };

+ 2 - 2
include/grpcpp/server.h

@@ -111,8 +111,8 @@ class Server : public ServerInterface, private GrpcLibraryCodegen {
     /// interceptors
     /// interceptors
     std::shared_ptr<Channel> InProcessChannelWithInterceptors(
     std::shared_ptr<Channel> InProcessChannelWithInterceptors(
         const ChannelArguments& args,
         const ChannelArguments& args,
-        std::unique_ptr<std::vector<
-            std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>>
+        std::vector<
+            std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
             interceptor_creators);
             interceptor_creators);
 
 
    private:
    private:

+ 4 - 4
package.xml

@@ -13,8 +13,8 @@
  <date>2018-01-19</date>
  <date>2018-01-19</date>
  <time>16:06:07</time>
  <time>16:06:07</time>
  <version>
  <version>
-  <release>1.17.0dev</release>
-  <api>1.17.0dev</api>
+  <release>1.18.0dev</release>
+  <api>1.18.0dev</api>
  </version>
  </version>
  <stability>
  <stability>
   <release>beta</release>
   <release>beta</release>
@@ -287,13 +287,13 @@
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy_factory.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy_factory.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy_registry.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy_registry.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/method_params.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/parse_address.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/parse_address.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/proxy_mapper.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/proxy_mapper.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/proxy_mapper_registry.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/proxy_mapper_registry.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver_factory.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver_factory.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver_registry.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver_registry.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver_result_parsing.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/retry_throttle.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/retry_throttle.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel_index.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel_index.h" role="src" />
@@ -731,12 +731,12 @@
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy_factory.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy_factory.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy_registry.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy_registry.cc" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/method_params.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/parse_address.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/parse_address.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/proxy_mapper.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/proxy_mapper.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/proxy_mapper_registry.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/proxy_mapper_registry.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver_registry.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver_registry.cc" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver_result_parsing.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/retry_throttle.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/retry_throttle.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel_index.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/subchannel_index.cc" role="src" />

+ 37 - 0
src/compiler/csharp_generator.cc

@@ -609,6 +609,42 @@ void GenerateBindServiceMethod(Printer* out, const ServiceDescriptor* service) {
   out->Print("\n");
   out->Print("\n");
 }
 }
 
 
+void GenerateBindServiceWithBinderMethod(Printer* out,
+                                         const ServiceDescriptor* service) {
+  out->Print(
+      "/// <summary>Register service method implementations with a service "
+      "binder. Useful when customizing the service binding logic.\n"
+      "/// Note: this method is part of an experimental API that can change or "
+      "be "
+      "removed without any prior notice.</summary>\n");
+  out->Print(
+      "/// <param name=\"serviceBinder\">Service methods will be bound by "
+      "calling <c>AddMethod</c> on this object."
+      "</param>\n");
+  out->Print(
+      "/// <param name=\"serviceImpl\">An object implementing the server-side"
+      " handling logic.</param>\n");
+  out->Print(
+      "public static void BindService(grpc::ServiceBinderBase serviceBinder, "
+      "$implclass$ "
+      "serviceImpl)\n",
+      "implclass", GetServerClassName(service));
+  out->Print("{\n");
+  out->Indent();
+
+  for (int i = 0; i < service->method_count(); i++) {
+    const MethodDescriptor* method = service->method(i);
+    out->Print(
+        "serviceBinder.AddMethod($methodfield$, serviceImpl.$methodname$);\n",
+        "methodfield", GetMethodFieldName(method), "methodname",
+        method->name());
+  }
+
+  out->Outdent();
+  out->Print("}\n");
+  out->Print("\n");
+}
+
 void GenerateService(Printer* out, const ServiceDescriptor* service,
 void GenerateService(Printer* out, const ServiceDescriptor* service,
                      bool generate_client, bool generate_server,
                      bool generate_client, bool generate_server,
                      bool internal_access) {
                      bool internal_access) {
@@ -637,6 +673,7 @@ void GenerateService(Printer* out, const ServiceDescriptor* service,
   }
   }
   if (generate_server) {
   if (generate_server) {
     GenerateBindServiceMethod(out, service);
     GenerateBindServiceMethod(out, service);
+    GenerateBindServiceWithBinderMethod(out, service);
   }
   }
 
 
   out->Outdent();
   out->Outdent();

+ 23 - 142
src/core/ext/filters/client_channel/client_channel.cc

@@ -34,9 +34,9 @@
 #include "src/core/ext/filters/client_channel/backup_poller.h"
 #include "src/core/ext/filters/client_channel/backup_poller.h"
 #include "src/core/ext/filters/client_channel/http_connect_handshaker.h"
 #include "src/core/ext/filters/client_channel/http_connect_handshaker.h"
 #include "src/core/ext/filters/client_channel/lb_policy_registry.h"
 #include "src/core/ext/filters/client_channel/lb_policy_registry.h"
-#include "src/core/ext/filters/client_channel/method_params.h"
 #include "src/core/ext/filters/client_channel/proxy_mapper_registry.h"
 #include "src/core/ext/filters/client_channel/proxy_mapper_registry.h"
 #include "src/core/ext/filters/client_channel/resolver_registry.h"
 #include "src/core/ext/filters/client_channel/resolver_registry.h"
+#include "src/core/ext/filters/client_channel/resolver_result_parsing.h"
 #include "src/core/ext/filters/client_channel/retry_throttle.h"
 #include "src/core/ext/filters/client_channel/retry_throttle.h"
 #include "src/core/ext/filters/client_channel/subchannel.h"
 #include "src/core/ext/filters/client_channel/subchannel.h"
 #include "src/core/ext/filters/deadline/deadline_filter.h"
 #include "src/core/ext/filters/deadline/deadline_filter.h"
@@ -63,6 +63,8 @@
 #include "src/core/lib/transport/status_metadata.h"
 #include "src/core/lib/transport/status_metadata.h"
 
 
 using grpc_core::internal::ClientChannelMethodParams;
 using grpc_core::internal::ClientChannelMethodParams;
+using grpc_core::internal::ClientChannelMethodParamsTable;
+using grpc_core::internal::ProcessedResolverResult;
 using grpc_core::internal::ServerRetryThrottleData;
 using grpc_core::internal::ServerRetryThrottleData;
 
 
 /* Client channel implementation */
 /* Client channel implementation */
@@ -83,10 +85,6 @@ grpc_core::TraceFlag grpc_client_channel_trace(false, "client_channel");
 
 
 struct external_connectivity_watcher;
 struct external_connectivity_watcher;
 
 
-typedef grpc_core::SliceHashTable<
-    grpc_core::RefCountedPtr<ClientChannelMethodParams>>
-    MethodParamsTable;
-
 typedef struct client_channel_channel_data {
 typedef struct client_channel_channel_data {
   grpc_core::OrphanablePtr<grpc_core::Resolver> resolver;
   grpc_core::OrphanablePtr<grpc_core::Resolver> resolver;
   bool started_resolving;
   bool started_resolving;
@@ -102,7 +100,7 @@ typedef struct client_channel_channel_data {
   /** retry throttle data */
   /** retry throttle data */
   grpc_core::RefCountedPtr<ServerRetryThrottleData> retry_throttle_data;
   grpc_core::RefCountedPtr<ServerRetryThrottleData> retry_throttle_data;
   /** maps method names to method_parameters structs */
   /** maps method names to method_parameters structs */
-  grpc_core::RefCountedPtr<MethodParamsTable> method_params_table;
+  grpc_core::RefCountedPtr<ClientChannelMethodParamsTable> method_params_table;
   /** incoming resolver result - set by resolver.next() */
   /** incoming resolver result - set by resolver.next() */
   grpc_channel_args* resolver_result;
   grpc_channel_args* resolver_result;
   /** a list of closures that are all waiting for resolver result to come in */
   /** a list of closures that are all waiting for resolver result to come in */
@@ -251,66 +249,6 @@ static void start_resolving_locked(channel_data* chand) {
                               &chand->on_resolver_result_changed);
                               &chand->on_resolver_result_changed);
 }
 }
 
 
-typedef struct {
-  char* server_name;
-  grpc_core::RefCountedPtr<ServerRetryThrottleData> retry_throttle_data;
-} service_config_parsing_state;
-
-static void parse_retry_throttle_params(
-    const grpc_json* field, service_config_parsing_state* parsing_state) {
-  if (strcmp(field->key, "retryThrottling") == 0) {
-    if (parsing_state->retry_throttle_data != nullptr) return;  // Duplicate.
-    if (field->type != GRPC_JSON_OBJECT) return;
-    int max_milli_tokens = 0;
-    int milli_token_ratio = 0;
-    for (grpc_json* sub_field = field->child; sub_field != nullptr;
-         sub_field = sub_field->next) {
-      if (sub_field->key == nullptr) return;
-      if (strcmp(sub_field->key, "maxTokens") == 0) {
-        if (max_milli_tokens != 0) return;  // Duplicate.
-        if (sub_field->type != GRPC_JSON_NUMBER) return;
-        max_milli_tokens = gpr_parse_nonnegative_int(sub_field->value);
-        if (max_milli_tokens == -1) return;
-        max_milli_tokens *= 1000;
-      } else if (strcmp(sub_field->key, "tokenRatio") == 0) {
-        if (milli_token_ratio != 0) return;  // Duplicate.
-        if (sub_field->type != GRPC_JSON_NUMBER) return;
-        // We support up to 3 decimal digits.
-        size_t whole_len = strlen(sub_field->value);
-        uint32_t multiplier = 1;
-        uint32_t decimal_value = 0;
-        const char* decimal_point = strchr(sub_field->value, '.');
-        if (decimal_point != nullptr) {
-          whole_len = static_cast<size_t>(decimal_point - sub_field->value);
-          multiplier = 1000;
-          size_t decimal_len = strlen(decimal_point + 1);
-          if (decimal_len > 3) decimal_len = 3;
-          if (!gpr_parse_bytes_to_uint32(decimal_point + 1, decimal_len,
-                                         &decimal_value)) {
-            return;
-          }
-          uint32_t decimal_multiplier = 1;
-          for (size_t i = 0; i < (3 - decimal_len); ++i) {
-            decimal_multiplier *= 10;
-          }
-          decimal_value *= decimal_multiplier;
-        }
-        uint32_t whole_value;
-        if (!gpr_parse_bytes_to_uint32(sub_field->value, whole_len,
-                                       &whole_value)) {
-          return;
-        }
-        milli_token_ratio =
-            static_cast<int>((whole_value * multiplier) + decimal_value);
-        if (milli_token_ratio <= 0) return;
-      }
-    }
-    parsing_state->retry_throttle_data =
-        grpc_core::internal::ServerRetryThrottleMap::GetDataForServer(
-            parsing_state->server_name, max_milli_tokens, milli_token_ratio);
-  }
-}
-
 // Invoked from the resolver NextLocked() callback when the resolver
 // Invoked from the resolver NextLocked() callback when the resolver
 // is shutting down.
 // is shutting down.
 static void on_resolver_shutdown_locked(channel_data* chand,
 static void on_resolver_shutdown_locked(channel_data* chand,
@@ -352,37 +290,6 @@ static void on_resolver_shutdown_locked(channel_data* chand,
   GRPC_ERROR_UNREF(error);
   GRPC_ERROR_UNREF(error);
 }
 }
 
 
-// Returns the LB policy name from the resolver result.
-static grpc_core::UniquePtr<char>
-get_lb_policy_name_from_resolver_result_locked(channel_data* chand) {
-  // Find LB policy name in channel args.
-  const grpc_arg* channel_arg =
-      grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_POLICY_NAME);
-  const char* lb_policy_name = grpc_channel_arg_get_string(channel_arg);
-  // Special case: If at least one balancer address is present, we use
-  // the grpclb policy, regardless of what the resolver actually specified.
-  channel_arg =
-      grpc_channel_args_find(chand->resolver_result, GRPC_ARG_LB_ADDRESSES);
-  if (channel_arg != nullptr && channel_arg->type == GRPC_ARG_POINTER) {
-    grpc_lb_addresses* addresses =
-        static_cast<grpc_lb_addresses*>(channel_arg->value.pointer.p);
-    if (grpc_lb_addresses_contains_balancer_address(*addresses)) {
-      if (lb_policy_name != nullptr &&
-          gpr_stricmp(lb_policy_name, "grpclb") != 0) {
-        gpr_log(GPR_INFO,
-                "resolver requested LB policy %s but provided at least one "
-                "balancer address -- forcing use of grpclb LB policy",
-                lb_policy_name);
-      }
-      lb_policy_name = "grpclb";
-    }
-  }
-  // Use pick_first if nothing was specified and we didn't select grpclb
-  // above.
-  if (lb_policy_name == nullptr) lb_policy_name = "pick_first";
-  return grpc_core::UniquePtr<char>(gpr_strdup(lb_policy_name));
-}
-
 static void request_reresolution_locked(void* arg, grpc_error* error) {
 static void request_reresolution_locked(void* arg, grpc_error* error) {
   reresolution_request_args* args =
   reresolution_request_args* args =
       static_cast<reresolution_request_args*>(arg);
       static_cast<reresolution_request_args*>(arg);
@@ -410,13 +317,14 @@ using TraceStringVector = grpc_core::InlinedVector<char*, 3>;
 // *connectivity_error to its initial connectivity state; otherwise,
 // *connectivity_error to its initial connectivity state; otherwise,
 // leaves them unchanged.
 // leaves them unchanged.
 static void create_new_lb_policy_locked(
 static void create_new_lb_policy_locked(
-    channel_data* chand, char* lb_policy_name,
+    channel_data* chand, char* lb_policy_name, grpc_json* lb_config,
     grpc_connectivity_state* connectivity_state,
     grpc_connectivity_state* connectivity_state,
     grpc_error** connectivity_error, TraceStringVector* trace_strings) {
     grpc_error** connectivity_error, TraceStringVector* trace_strings) {
   grpc_core::LoadBalancingPolicy::Args lb_policy_args;
   grpc_core::LoadBalancingPolicy::Args lb_policy_args;
   lb_policy_args.combiner = chand->combiner;
   lb_policy_args.combiner = chand->combiner;
   lb_policy_args.client_channel_factory = chand->client_channel_factory;
   lb_policy_args.client_channel_factory = chand->client_channel_factory;
   lb_policy_args.args = chand->resolver_result;
   lb_policy_args.args = chand->resolver_result;
+  lb_policy_args.lb_config = lb_config;
   grpc_core::OrphanablePtr<grpc_core::LoadBalancingPolicy> new_lb_policy =
   grpc_core::OrphanablePtr<grpc_core::LoadBalancingPolicy> new_lb_policy =
       grpc_core::LoadBalancingPolicyRegistry::CreateLoadBalancingPolicy(
       grpc_core::LoadBalancingPolicyRegistry::CreateLoadBalancingPolicy(
           lb_policy_name, lb_policy_args);
           lb_policy_name, lb_policy_args);
@@ -473,44 +381,6 @@ static void create_new_lb_policy_locked(
   }
   }
 }
 }
 
 
-// Returns the service config (as a JSON string) from the resolver result.
-// Also updates state in chand.
-static grpc_core::UniquePtr<char>
-get_service_config_from_resolver_result_locked(channel_data* chand) {
-  const grpc_arg* channel_arg =
-      grpc_channel_args_find(chand->resolver_result, GRPC_ARG_SERVICE_CONFIG);
-  const char* service_config_json = grpc_channel_arg_get_string(channel_arg);
-  if (service_config_json != nullptr) {
-    if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_INFO, "chand=%p: resolver returned service config: \"%s\"",
-              chand, service_config_json);
-    }
-    grpc_core::UniquePtr<grpc_core::ServiceConfig> service_config =
-        grpc_core::ServiceConfig::Create(service_config_json);
-    if (service_config != nullptr) {
-      if (chand->enable_retries) {
-        channel_arg =
-            grpc_channel_args_find(chand->resolver_result, GRPC_ARG_SERVER_URI);
-        const char* server_uri = grpc_channel_arg_get_string(channel_arg);
-        GPR_ASSERT(server_uri != nullptr);
-        grpc_uri* uri = grpc_uri_parse(server_uri, true);
-        GPR_ASSERT(uri->path[0] != '\0');
-        service_config_parsing_state parsing_state;
-        parsing_state.server_name =
-            uri->path[0] == '/' ? uri->path + 1 : uri->path;
-        service_config->ParseGlobalParams(parse_retry_throttle_params,
-                                          &parsing_state);
-        grpc_uri_destroy(uri);
-        chand->retry_throttle_data =
-            std::move(parsing_state.retry_throttle_data);
-      }
-      chand->method_params_table = service_config->CreateMethodConfigTable(
-          ClientChannelMethodParams::CreateFromJson);
-    }
-  }
-  return grpc_core::UniquePtr<char>(gpr_strdup(service_config_json));
-}
-
 static void maybe_add_trace_message_for_address_changes_locked(
 static void maybe_add_trace_message_for_address_changes_locked(
     channel_data* chand, TraceStringVector* trace_strings) {
     channel_data* chand, TraceStringVector* trace_strings) {
   int resolution_contains_addresses = false;
   int resolution_contains_addresses = false;
@@ -597,9 +467,23 @@ static void on_resolver_result_changed_locked(void* arg, grpc_error* error) {
     if (grpc_client_channel_trace.enabled()) {
     if (grpc_client_channel_trace.enabled()) {
       gpr_log(GPR_INFO, "chand=%p: resolver transient failure", chand);
       gpr_log(GPR_INFO, "chand=%p: resolver transient failure", chand);
     }
     }
+    // Don't override connectivity state if we already have an LB policy.
+    if (chand->lb_policy != nullptr) set_connectivity_state = false;
   } else {
   } else {
+    // Parse the resolver result.
+    ProcessedResolverResult resolver_result(chand->resolver_result,
+                                            chand->enable_retries);
+    chand->retry_throttle_data = resolver_result.retry_throttle_data();
+    chand->method_params_table = resolver_result.method_params_table();
+    grpc_core::UniquePtr<char> service_config_json =
+        resolver_result.service_config_json();
+    if (service_config_json != nullptr && grpc_client_channel_trace.enabled()) {
+      gpr_log(GPR_INFO, "chand=%p: resolver returned service config: \"%s\"",
+              chand, service_config_json.get());
+    }
     grpc_core::UniquePtr<char> lb_policy_name =
     grpc_core::UniquePtr<char> lb_policy_name =
-        get_lb_policy_name_from_resolver_result_locked(chand);
+        resolver_result.lb_policy_name();
+    grpc_json* lb_policy_config = resolver_result.lb_policy_config();
     // Check to see if we're already using the right LB policy.
     // Check to see if we're already using the right LB policy.
     // Note: It's safe to use chand->info_lb_policy_name here without
     // Note: It's safe to use chand->info_lb_policy_name here without
     // taking a lock on chand->info_mu, because this function is the
     // taking a lock on chand->info_mu, because this function is the
@@ -614,19 +498,16 @@ static void on_resolver_result_changed_locked(void* arg, grpc_error* error) {
         gpr_log(GPR_INFO, "chand=%p: updating existing LB policy \"%s\" (%p)",
         gpr_log(GPR_INFO, "chand=%p: updating existing LB policy \"%s\" (%p)",
                 chand, lb_policy_name.get(), chand->lb_policy.get());
                 chand, lb_policy_name.get(), chand->lb_policy.get());
       }
       }
-      chand->lb_policy->UpdateLocked(*chand->resolver_result);
+      chand->lb_policy->UpdateLocked(*chand->resolver_result, lb_policy_config);
       // No need to set the channel's connectivity state; the existing
       // No need to set the channel's connectivity state; the existing
       // watch on the LB policy will take care of that.
       // watch on the LB policy will take care of that.
       set_connectivity_state = false;
       set_connectivity_state = false;
     } else {
     } else {
       // Instantiate new LB policy.
       // Instantiate new LB policy.
-      create_new_lb_policy_locked(chand, lb_policy_name.get(),
+      create_new_lb_policy_locked(chand, lb_policy_name.get(), lb_policy_config,
                                   &connectivity_state, &connectivity_error,
                                   &connectivity_state, &connectivity_error,
                                   &trace_strings);
                                   &trace_strings);
     }
     }
-    // Find service config.
-    grpc_core::UniquePtr<char> service_config_json =
-        get_service_config_from_resolver_result_locked(chand);
     // Note: It's safe to use chand->info_service_config_json here without
     // Note: It's safe to use chand->info_service_config_json here without
     // taking a lock on chand->info_mu, because this function is the
     // taking a lock on chand->info_mu, because this function is the
     // only thing that modifies its value, and it can only be invoked
     // only thing that modifies its value, and it can only be invoked

+ 6 - 3
src/core/ext/filters/client_channel/lb_policy.h

@@ -58,6 +58,8 @@ class LoadBalancingPolicy
     /// Note that the LB policy gets the set of addresses from the
     /// Note that the LB policy gets the set of addresses from the
     /// GRPC_ARG_LB_ADDRESSES channel arg.
     /// GRPC_ARG_LB_ADDRESSES channel arg.
     grpc_channel_args* args = nullptr;
     grpc_channel_args* args = nullptr;
+    /// Load balancing config from the resolver.
+    grpc_json* lb_config = nullptr;
   };
   };
 
 
   /// State used for an LB pick.
   /// State used for an LB pick.
@@ -92,10 +94,11 @@ class LoadBalancingPolicy
   LoadBalancingPolicy(const LoadBalancingPolicy&) = delete;
   LoadBalancingPolicy(const LoadBalancingPolicy&) = delete;
   LoadBalancingPolicy& operator=(const LoadBalancingPolicy&) = delete;
   LoadBalancingPolicy& operator=(const LoadBalancingPolicy&) = delete;
 
 
-  /// Updates the policy with a new set of \a args from the resolver.
-  /// Note that the LB policy gets the set of addresses from the
+  /// Updates the policy with a new set of \a args and a new \a lb_config from
+  /// the resolver. Note that the LB policy gets the set of addresses from the
   /// GRPC_ARG_LB_ADDRESSES channel arg.
   /// GRPC_ARG_LB_ADDRESSES channel arg.
-  virtual void UpdateLocked(const grpc_channel_args& args) GRPC_ABSTRACT;
+  virtual void UpdateLocked(const grpc_channel_args& args,
+                            grpc_json* lb_config) GRPC_ABSTRACT;
 
 
   /// Finds an appropriate subchannel for a call, based on data in \a pick.
   /// Finds an appropriate subchannel for a call, based on data in \a pick.
   /// \a pick must remain alive until the pick is complete.
   /// \a pick must remain alive until the pick is complete.

+ 4 - 3
src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc

@@ -123,7 +123,8 @@ class GrpcLb : public LoadBalancingPolicy {
  public:
  public:
   GrpcLb(const grpc_lb_addresses* addresses, const Args& args);
   GrpcLb(const grpc_lb_addresses* addresses, const Args& args);
 
 
-  void UpdateLocked(const grpc_channel_args& args) override;
+  void UpdateLocked(const grpc_channel_args& args,
+                    grpc_json* lb_config) override;
   bool PickLocked(PickState* pick, grpc_error** error) override;
   bool PickLocked(PickState* pick, grpc_error** error) override;
   void CancelPickLocked(PickState* pick, grpc_error* error) override;
   void CancelPickLocked(PickState* pick, grpc_error* error) override;
   void CancelMatchingPicksLocked(uint32_t initial_metadata_flags_mask,
   void CancelMatchingPicksLocked(uint32_t initial_metadata_flags_mask,
@@ -1331,7 +1332,7 @@ void GrpcLb::ProcessChannelArgsLocked(const grpc_channel_args& args) {
   grpc_channel_args_destroy(lb_channel_args);
   grpc_channel_args_destroy(lb_channel_args);
 }
 }
 
 
-void GrpcLb::UpdateLocked(const grpc_channel_args& args) {
+void GrpcLb::UpdateLocked(const grpc_channel_args& args, grpc_json* lb_config) {
   ProcessChannelArgsLocked(args);
   ProcessChannelArgsLocked(args);
   // Update the existing RR policy.
   // Update the existing RR policy.
   if (rr_policy_ != nullptr) CreateOrUpdateRoundRobinPolicyLocked();
   if (rr_policy_ != nullptr) CreateOrUpdateRoundRobinPolicyLocked();
@@ -1727,7 +1728,7 @@ void GrpcLb::CreateOrUpdateRoundRobinPolicyLocked() {
       gpr_log(GPR_INFO, "[grpclb %p] Updating RR policy %p", this,
       gpr_log(GPR_INFO, "[grpclb %p] Updating RR policy %p", this,
               rr_policy_.get());
               rr_policy_.get());
     }
     }
-    rr_policy_->UpdateLocked(*args);
+    rr_policy_->UpdateLocked(*args, nullptr);
   } else {
   } else {
     LoadBalancingPolicy::Args lb_policy_args;
     LoadBalancingPolicy::Args lb_policy_args;
     lb_policy_args.combiner = combiner();
     lb_policy_args.combiner = combiner();

+ 5 - 3
src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc

@@ -46,7 +46,8 @@ class PickFirst : public LoadBalancingPolicy {
  public:
  public:
   explicit PickFirst(const Args& args);
   explicit PickFirst(const Args& args);
 
 
-  void UpdateLocked(const grpc_channel_args& args) override;
+  void UpdateLocked(const grpc_channel_args& args,
+                    grpc_json* lb_config) override;
   bool PickLocked(PickState* pick, grpc_error** error) override;
   bool PickLocked(PickState* pick, grpc_error** error) override;
   void CancelPickLocked(PickState* pick, grpc_error* error) override;
   void CancelPickLocked(PickState* pick, grpc_error* error) override;
   void CancelMatchingPicksLocked(uint32_t initial_metadata_flags_mask,
   void CancelMatchingPicksLocked(uint32_t initial_metadata_flags_mask,
@@ -159,7 +160,7 @@ PickFirst::PickFirst(const Args& args) : LoadBalancingPolicy(args) {
   if (grpc_lb_pick_first_trace.enabled()) {
   if (grpc_lb_pick_first_trace.enabled()) {
     gpr_log(GPR_INFO, "Pick First %p created.", this);
     gpr_log(GPR_INFO, "Pick First %p created.", this);
   }
   }
-  UpdateLocked(*args.args);
+  UpdateLocked(*args.args, args.lb_config);
   grpc_subchannel_index_ref();
   grpc_subchannel_index_ref();
 }
 }
 
 
@@ -333,7 +334,8 @@ void PickFirst::UpdateChildRefsLocked() {
   child_subchannels_ = std::move(cs);
   child_subchannels_ = std::move(cs);
 }
 }
 
 
-void PickFirst::UpdateLocked(const grpc_channel_args& args) {
+void PickFirst::UpdateLocked(const grpc_channel_args& args,
+                             grpc_json* lb_config) {
   AutoChildRefsUpdater guard(this);
   AutoChildRefsUpdater guard(this);
   const grpc_arg* arg = grpc_channel_args_find(&args, GRPC_ARG_LB_ADDRESSES);
   const grpc_arg* arg = grpc_channel_args_find(&args, GRPC_ARG_LB_ADDRESSES);
   if (arg == nullptr || arg->type != GRPC_ARG_POINTER) {
   if (arg == nullptr || arg->type != GRPC_ARG_POINTER) {

+ 5 - 3
src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc

@@ -57,7 +57,8 @@ class RoundRobin : public LoadBalancingPolicy {
  public:
  public:
   explicit RoundRobin(const Args& args);
   explicit RoundRobin(const Args& args);
 
 
-  void UpdateLocked(const grpc_channel_args& args) override;
+  void UpdateLocked(const grpc_channel_args& args,
+                    grpc_json* lb_config) override;
   bool PickLocked(PickState* pick, grpc_error** error) override;
   bool PickLocked(PickState* pick, grpc_error** error) override;
   void CancelPickLocked(PickState* pick, grpc_error* error) override;
   void CancelPickLocked(PickState* pick, grpc_error* error) override;
   void CancelMatchingPicksLocked(uint32_t initial_metadata_flags_mask,
   void CancelMatchingPicksLocked(uint32_t initial_metadata_flags_mask,
@@ -232,7 +233,7 @@ RoundRobin::RoundRobin(const Args& args) : LoadBalancingPolicy(args) {
   gpr_mu_init(&child_refs_mu_);
   gpr_mu_init(&child_refs_mu_);
   grpc_connectivity_state_init(&state_tracker_, GRPC_CHANNEL_IDLE,
   grpc_connectivity_state_init(&state_tracker_, GRPC_CHANNEL_IDLE,
                                "round_robin");
                                "round_robin");
-  UpdateLocked(*args.args);
+  UpdateLocked(*args.args, args.lb_config);
   if (grpc_lb_round_robin_trace.enabled()) {
   if (grpc_lb_round_robin_trace.enabled()) {
     gpr_log(GPR_INFO, "[RR %p] Created with %" PRIuPTR " subchannels", this,
     gpr_log(GPR_INFO, "[RR %p] Created with %" PRIuPTR " subchannels", this,
             subchannel_list_->num_subchannels());
             subchannel_list_->num_subchannels());
@@ -664,7 +665,8 @@ void RoundRobin::NotifyOnStateChangeLocked(grpc_connectivity_state* current,
                                                  notify);
                                                  notify);
 }
 }
 
 
-void RoundRobin::UpdateLocked(const grpc_channel_args& args) {
+void RoundRobin::UpdateLocked(const grpc_channel_args& args,
+                              grpc_json* lb_config) {
   const grpc_arg* arg = grpc_channel_args_find(&args, GRPC_ARG_LB_ADDRESSES);
   const grpc_arg* arg = grpc_channel_args_find(&args, GRPC_ARG_LB_ADDRESSES);
   AutoChildRefsUpdater guard(this);
   AutoChildRefsUpdater guard(this);
   if (GPR_UNLIKELY(arg == nullptr || arg->type != GRPC_ARG_POINTER)) {
   if (GPR_UNLIKELY(arg == nullptr || arg->type != GRPC_ARG_POINTER)) {

+ 7 - 3
src/core/ext/filters/client_channel/lb_policy/xds/xds.cc

@@ -118,7 +118,8 @@ class XdsLb : public LoadBalancingPolicy {
  public:
  public:
   XdsLb(const grpc_lb_addresses* addresses, const Args& args);
   XdsLb(const grpc_lb_addresses* addresses, const Args& args);
 
 
-  void UpdateLocked(const grpc_channel_args& args) override;
+  void UpdateLocked(const grpc_channel_args& args,
+                    grpc_json* lb_config) override;
   bool PickLocked(PickState* pick, grpc_error** error) override;
   bool PickLocked(PickState* pick, grpc_error** error) override;
   void CancelPickLocked(PickState* pick, grpc_error* error) override;
   void CancelPickLocked(PickState* pick, grpc_error* error) override;
   void CancelMatchingPicksLocked(uint32_t initial_metadata_flags_mask,
   void CancelMatchingPicksLocked(uint32_t initial_metadata_flags_mask,
@@ -1010,6 +1011,7 @@ grpc_channel_args* BuildBalancerChannelArgs(
 // ctor and dtor
 // ctor and dtor
 //
 //
 
 
+// TODO(vishalpowar): Use lb_config in args to configure LB policy.
 XdsLb::XdsLb(const grpc_lb_addresses* addresses,
 XdsLb::XdsLb(const grpc_lb_addresses* addresses,
              const LoadBalancingPolicy::Args& args)
              const LoadBalancingPolicy::Args& args)
     : LoadBalancingPolicy(args),
     : LoadBalancingPolicy(args),
@@ -1314,7 +1316,8 @@ void XdsLb::ProcessChannelArgsLocked(const grpc_channel_args& args) {
   grpc_channel_args_destroy(lb_channel_args);
   grpc_channel_args_destroy(lb_channel_args);
 }
 }
 
 
-void XdsLb::UpdateLocked(const grpc_channel_args& args) {
+// TODO(vishalpowar): Use lb_config to configure LB policy.
+void XdsLb::UpdateLocked(const grpc_channel_args& args, grpc_json* lb_config) {
   ProcessChannelArgsLocked(args);
   ProcessChannelArgsLocked(args);
   // Update the existing child policy.
   // Update the existing child policy.
   // Note: We have disabled fallback mode in the code, so this child policy must
   // Note: We have disabled fallback mode in the code, so this child policy must
@@ -1672,7 +1675,8 @@ void XdsLb::CreateOrUpdateChildPolicyLocked() {
       gpr_log(GPR_INFO, "[xdslb %p] Updating the child policy %p", this,
       gpr_log(GPR_INFO, "[xdslb %p] Updating the child policy %p", this,
               child_policy_.get());
               child_policy_.get());
     }
     }
-    child_policy_->UpdateLocked(*args);
+    // TODO(vishalpowar): Pass the correct LB config.
+    child_policy_->UpdateLocked(*args, nullptr);
   } else {
   } else {
     LoadBalancingPolicy::Args lb_policy_args;
     LoadBalancingPolicy::Args lb_policy_args;
     lb_policy_args.combiner = combiner();
     lb_policy_args.combiner = combiner();

+ 5 - 0
src/core/ext/filters/client_channel/lb_policy_registry.cc

@@ -94,4 +94,9 @@ LoadBalancingPolicyRegistry::CreateLoadBalancingPolicy(
   return factory->CreateLoadBalancingPolicy(args);
   return factory->CreateLoadBalancingPolicy(args);
 }
 }
 
 
+bool LoadBalancingPolicyRegistry::LoadBalancingPolicyExists(const char* name) {
+  GPR_ASSERT(g_state != nullptr);
+  return g_state->GetLoadBalancingPolicyFactory(name) != nullptr;
+}
+
 }  // namespace grpc_core
 }  // namespace grpc_core

+ 4 - 0
src/core/ext/filters/client_channel/lb_policy_registry.h

@@ -47,6 +47,10 @@ class LoadBalancingPolicyRegistry {
   /// Creates an LB policy of the type specified by \a name.
   /// Creates an LB policy of the type specified by \a name.
   static OrphanablePtr<LoadBalancingPolicy> CreateLoadBalancingPolicy(
   static OrphanablePtr<LoadBalancingPolicy> CreateLoadBalancingPolicy(
       const char* name, const LoadBalancingPolicy::Args& args);
       const char* name, const LoadBalancingPolicy::Args& args);
+
+  /// Returns true if the LB policy factory specified by \a name exists in this
+  /// registry.
+  static bool LoadBalancingPolicyExists(const char* name);
 };
 };
 
 
 }  // namespace grpc_core
 }  // namespace grpc_core

+ 0 - 178
src/core/ext/filters/client_channel/method_params.cc

@@ -1,178 +0,0 @@
-/*
- *
- * Copyright 2015 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include <grpc/support/port_platform.h>
-
-#include <stdio.h>
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-
-#include "src/core/ext/filters/client_channel/method_params.h"
-#include "src/core/lib/channel/status_util.h"
-#include "src/core/lib/gpr/string.h"
-#include "src/core/lib/gprpp/memory.h"
-
-// As per the retry design, we do not allow more than 5 retry attempts.
-#define MAX_MAX_RETRY_ATTEMPTS 5
-
-namespace grpc_core {
-namespace internal {
-
-namespace {
-
-bool ParseWaitForReady(
-    grpc_json* field, ClientChannelMethodParams::WaitForReady* wait_for_ready) {
-  if (field->type != GRPC_JSON_TRUE && field->type != GRPC_JSON_FALSE) {
-    return false;
-  }
-  *wait_for_ready = field->type == GRPC_JSON_TRUE
-                        ? ClientChannelMethodParams::WAIT_FOR_READY_TRUE
-                        : ClientChannelMethodParams::WAIT_FOR_READY_FALSE;
-  return true;
-}
-
-// Parses a JSON field of the form generated for a google.proto.Duration
-// proto message, as per:
-//   https://developers.google.com/protocol-buffers/docs/proto3#json
-bool ParseDuration(grpc_json* field, grpc_millis* duration) {
-  if (field->type != GRPC_JSON_STRING) return false;
-  size_t len = strlen(field->value);
-  if (field->value[len - 1] != 's') return false;
-  UniquePtr<char> buf(gpr_strdup(field->value));
-  *(buf.get() + len - 1) = '\0';  // Remove trailing 's'.
-  char* decimal_point = strchr(buf.get(), '.');
-  int nanos = 0;
-  if (decimal_point != nullptr) {
-    *decimal_point = '\0';
-    nanos = gpr_parse_nonnegative_int(decimal_point + 1);
-    if (nanos == -1) {
-      return false;
-    }
-    int num_digits = static_cast<int>(strlen(decimal_point + 1));
-    if (num_digits > 9) {  // We don't accept greater precision than nanos.
-      return false;
-    }
-    for (int i = 0; i < (9 - num_digits); ++i) {
-      nanos *= 10;
-    }
-  }
-  int seconds =
-      decimal_point == buf.get() ? 0 : gpr_parse_nonnegative_int(buf.get());
-  if (seconds == -1) return false;
-  *duration = seconds * GPR_MS_PER_SEC + nanos / GPR_NS_PER_MS;
-  return true;
-}
-
-UniquePtr<ClientChannelMethodParams::RetryPolicy> ParseRetryPolicy(
-    grpc_json* field) {
-  auto retry_policy = MakeUnique<ClientChannelMethodParams::RetryPolicy>();
-  if (field->type != GRPC_JSON_OBJECT) return nullptr;
-  for (grpc_json* sub_field = field->child; sub_field != nullptr;
-       sub_field = sub_field->next) {
-    if (sub_field->key == nullptr) return nullptr;
-    if (strcmp(sub_field->key, "maxAttempts") == 0) {
-      if (retry_policy->max_attempts != 0) return nullptr;  // Duplicate.
-      if (sub_field->type != GRPC_JSON_NUMBER) return nullptr;
-      retry_policy->max_attempts = gpr_parse_nonnegative_int(sub_field->value);
-      if (retry_policy->max_attempts <= 1) return nullptr;
-      if (retry_policy->max_attempts > MAX_MAX_RETRY_ATTEMPTS) {
-        gpr_log(GPR_ERROR,
-                "service config: clamped retryPolicy.maxAttempts at %d",
-                MAX_MAX_RETRY_ATTEMPTS);
-        retry_policy->max_attempts = MAX_MAX_RETRY_ATTEMPTS;
-      }
-    } else if (strcmp(sub_field->key, "initialBackoff") == 0) {
-      if (retry_policy->initial_backoff > 0) return nullptr;  // Duplicate.
-      if (!ParseDuration(sub_field, &retry_policy->initial_backoff)) {
-        return nullptr;
-      }
-      if (retry_policy->initial_backoff == 0) return nullptr;
-    } else if (strcmp(sub_field->key, "maxBackoff") == 0) {
-      if (retry_policy->max_backoff > 0) return nullptr;  // Duplicate.
-      if (!ParseDuration(sub_field, &retry_policy->max_backoff)) {
-        return nullptr;
-      }
-      if (retry_policy->max_backoff == 0) return nullptr;
-    } else if (strcmp(sub_field->key, "backoffMultiplier") == 0) {
-      if (retry_policy->backoff_multiplier != 0) return nullptr;  // Duplicate.
-      if (sub_field->type != GRPC_JSON_NUMBER) return nullptr;
-      if (sscanf(sub_field->value, "%f", &retry_policy->backoff_multiplier) !=
-          1) {
-        return nullptr;
-      }
-      if (retry_policy->backoff_multiplier <= 0) return nullptr;
-    } else if (strcmp(sub_field->key, "retryableStatusCodes") == 0) {
-      if (!retry_policy->retryable_status_codes.Empty()) {
-        return nullptr;  // Duplicate.
-      }
-      if (sub_field->type != GRPC_JSON_ARRAY) return nullptr;
-      for (grpc_json* element = sub_field->child; element != nullptr;
-           element = element->next) {
-        if (element->type != GRPC_JSON_STRING) return nullptr;
-        grpc_status_code status;
-        if (!grpc_status_code_from_string(element->value, &status)) {
-          return nullptr;
-        }
-        retry_policy->retryable_status_codes.Add(status);
-      }
-      if (retry_policy->retryable_status_codes.Empty()) return nullptr;
-    }
-  }
-  // Make sure required fields are set.
-  if (retry_policy->max_attempts == 0 || retry_policy->initial_backoff == 0 ||
-      retry_policy->max_backoff == 0 || retry_policy->backoff_multiplier == 0 ||
-      retry_policy->retryable_status_codes.Empty()) {
-    return nullptr;
-  }
-  return retry_policy;
-}
-
-}  // namespace
-
-RefCountedPtr<ClientChannelMethodParams>
-ClientChannelMethodParams::CreateFromJson(const grpc_json* json) {
-  RefCountedPtr<ClientChannelMethodParams> method_params =
-      MakeRefCounted<ClientChannelMethodParams>();
-  for (grpc_json* field = json->child; field != nullptr; field = field->next) {
-    if (field->key == nullptr) continue;
-    if (strcmp(field->key, "waitForReady") == 0) {
-      if (method_params->wait_for_ready_ != WAIT_FOR_READY_UNSET) {
-        return nullptr;  // Duplicate.
-      }
-      if (!ParseWaitForReady(field, &method_params->wait_for_ready_)) {
-        return nullptr;
-      }
-    } else if (strcmp(field->key, "timeout") == 0) {
-      if (method_params->timeout_ > 0) return nullptr;  // Duplicate.
-      if (!ParseDuration(field, &method_params->timeout_)) return nullptr;
-    } else if (strcmp(field->key, "retryPolicy") == 0) {
-      if (method_params->retry_policy_ != nullptr) {
-        return nullptr;  // Duplicate.
-      }
-      method_params->retry_policy_ = ParseRetryPolicy(field);
-      if (method_params->retry_policy_ == nullptr) return nullptr;
-    }
-  }
-  return method_params;
-}
-
-}  // namespace internal
-}  // namespace grpc_core

+ 0 - 78
src/core/ext/filters/client_channel/method_params.h

@@ -1,78 +0,0 @@
-/*
- *
- * Copyright 2015 gRPC authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_METHOD_PARAMS_H
-#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_METHOD_PARAMS_H
-
-#include <grpc/support/port_platform.h>
-
-#include "src/core/lib/channel/status_util.h"
-#include "src/core/lib/gprpp/ref_counted.h"
-#include "src/core/lib/gprpp/ref_counted_ptr.h"
-#include "src/core/lib/iomgr/exec_ctx.h"  // for grpc_millis
-#include "src/core/lib/json/json.h"
-
-namespace grpc_core {
-namespace internal {
-
-class ClientChannelMethodParams : public RefCounted<ClientChannelMethodParams> {
- public:
-  enum WaitForReady {
-    WAIT_FOR_READY_UNSET = 0,
-    WAIT_FOR_READY_FALSE,
-    WAIT_FOR_READY_TRUE
-  };
-
-  struct RetryPolicy {
-    int max_attempts = 0;
-    grpc_millis initial_backoff = 0;
-    grpc_millis max_backoff = 0;
-    float backoff_multiplier = 0;
-    StatusCodeSet retryable_status_codes;
-  };
-
-  /// Creates a method_parameters object from \a json.
-  /// Intended for use with ServiceConfig::CreateMethodConfigTable().
-  static RefCountedPtr<ClientChannelMethodParams> CreateFromJson(
-      const grpc_json* json);
-
-  grpc_millis timeout() const { return timeout_; }
-  WaitForReady wait_for_ready() const { return wait_for_ready_; }
-  const RetryPolicy* retry_policy() const { return retry_policy_.get(); }
-
- private:
-  // So New() can call our private ctor.
-  template <typename T, typename... Args>
-  friend T* grpc_core::New(Args&&... args);
-
-  // So Delete() can call our private dtor.
-  template <typename T>
-  friend void grpc_core::Delete(T*);
-
-  ClientChannelMethodParams() {}
-  virtual ~ClientChannelMethodParams() {}
-
-  grpc_millis timeout_ = 0;
-  WaitForReady wait_for_ready_ = WAIT_FOR_READY_UNSET;
-  UniquePtr<RetryPolicy> retry_policy_;
-};
-
-}  // namespace internal
-}  // namespace grpc_core
-
-#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_METHOD_PARAMS_H */

+ 5 - 18
src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc

@@ -308,13 +308,12 @@ void AresDnsResolver::OnResolvedLocked(void* arg, grpc_error* error) {
   gpr_free(r->pending_request_);
   gpr_free(r->pending_request_);
   r->pending_request_ = nullptr;
   r->pending_request_ = nullptr;
   if (r->lb_addresses_ != nullptr) {
   if (r->lb_addresses_ != nullptr) {
-    static const char* args_to_remove[2];
+    static const char* args_to_remove[1];
     size_t num_args_to_remove = 0;
     size_t num_args_to_remove = 0;
-    grpc_arg new_args[3];
+    grpc_arg args_to_add[2];
     size_t num_args_to_add = 0;
     size_t num_args_to_add = 0;
-    new_args[num_args_to_add++] =
+    args_to_add[num_args_to_add++] =
         grpc_lb_addresses_create_channel_arg(r->lb_addresses_);
         grpc_lb_addresses_create_channel_arg(r->lb_addresses_);
-    grpc_core::UniquePtr<grpc_core::ServiceConfig> service_config;
     char* service_config_string = nullptr;
     char* service_config_string = nullptr;
     if (r->service_config_json_ != nullptr) {
     if (r->service_config_json_ != nullptr) {
       service_config_string = ChooseServiceConfig(r->service_config_json_);
       service_config_string = ChooseServiceConfig(r->service_config_json_);
@@ -323,24 +322,12 @@ void AresDnsResolver::OnResolvedLocked(void* arg, grpc_error* error) {
         gpr_log(GPR_INFO, "selected service config choice: %s",
         gpr_log(GPR_INFO, "selected service config choice: %s",
                 service_config_string);
                 service_config_string);
         args_to_remove[num_args_to_remove++] = GRPC_ARG_SERVICE_CONFIG;
         args_to_remove[num_args_to_remove++] = GRPC_ARG_SERVICE_CONFIG;
-        new_args[num_args_to_add++] = grpc_channel_arg_string_create(
+        args_to_add[num_args_to_add++] = grpc_channel_arg_string_create(
             (char*)GRPC_ARG_SERVICE_CONFIG, service_config_string);
             (char*)GRPC_ARG_SERVICE_CONFIG, service_config_string);
-        service_config =
-            grpc_core::ServiceConfig::Create(service_config_string);
-        if (service_config != nullptr) {
-          const char* lb_policy_name =
-              service_config->GetLoadBalancingPolicyName();
-          if (lb_policy_name != nullptr) {
-            args_to_remove[num_args_to_remove++] = GRPC_ARG_LB_POLICY_NAME;
-            new_args[num_args_to_add++] = grpc_channel_arg_string_create(
-                (char*)GRPC_ARG_LB_POLICY_NAME,
-                const_cast<char*>(lb_policy_name));
-          }
-        }
       }
       }
     }
     }
     result = grpc_channel_args_copy_and_add_and_remove(
     result = grpc_channel_args_copy_and_add_and_remove(
-        r->channel_args_, args_to_remove, num_args_to_remove, new_args,
+        r->channel_args_, args_to_remove, num_args_to_remove, args_to_add,
         num_args_to_add);
         num_args_to_add);
     gpr_free(service_config_string);
     gpr_free(service_config_string);
     grpc_lb_addresses_destroy(r->lb_addresses_);
     grpc_lb_addresses_destroy(r->lb_addresses_);

+ 15 - 2
src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc

@@ -103,7 +103,7 @@ void FakeResolver::NextLocked(grpc_channel_args** target_result,
 }
 }
 
 
 void FakeResolver::RequestReresolutionLocked() {
 void FakeResolver::RequestReresolutionLocked() {
-  if (reresolution_results_ != nullptr) {
+  if (reresolution_results_ != nullptr || return_failure_) {
     grpc_channel_args_destroy(next_results_);
     grpc_channel_args_destroy(next_results_);
     next_results_ = grpc_channel_args_copy(reresolution_results_);
     next_results_ = grpc_channel_args_copy(reresolution_results_);
     MaybeFinishNextLocked();
     MaybeFinishNextLocked();
@@ -141,6 +141,7 @@ struct SetResponseClosureArg {
   grpc_closure set_response_closure;
   grpc_closure set_response_closure;
   FakeResolverResponseGenerator* generator;
   FakeResolverResponseGenerator* generator;
   grpc_channel_args* response;
   grpc_channel_args* response;
+  bool immediate = true;
 };
 };
 
 
 void FakeResolverResponseGenerator::SetResponseLocked(void* arg,
 void FakeResolverResponseGenerator::SetResponseLocked(void* arg,
@@ -194,7 +195,7 @@ void FakeResolverResponseGenerator::SetFailureLocked(void* arg,
   SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
   SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
   FakeResolver* resolver = closure_arg->generator->resolver_;
   FakeResolver* resolver = closure_arg->generator->resolver_;
   resolver->return_failure_ = true;
   resolver->return_failure_ = true;
-  resolver->MaybeFinishNextLocked();
+  if (closure_arg->immediate) resolver->MaybeFinishNextLocked();
   Delete(closure_arg);
   Delete(closure_arg);
 }
 }
 
 
@@ -209,6 +210,18 @@ void FakeResolverResponseGenerator::SetFailure() {
       GRPC_ERROR_NONE);
       GRPC_ERROR_NONE);
 }
 }
 
 
+void FakeResolverResponseGenerator::SetFailureOnReresolution() {
+  GPR_ASSERT(resolver_ != nullptr);
+  SetResponseClosureArg* closure_arg = New<SetResponseClosureArg>();
+  closure_arg->generator = this;
+  closure_arg->immediate = false;
+  GRPC_CLOSURE_SCHED(
+      GRPC_CLOSURE_INIT(&closure_arg->set_response_closure, SetFailureLocked,
+                        closure_arg,
+                        grpc_combiner_scheduler(resolver_->combiner())),
+      GRPC_ERROR_NONE);
+}
+
 namespace {
 namespace {
 
 
 static void* response_generator_arg_copy(void* p) {
 static void* response_generator_arg_copy(void* p) {

+ 4 - 0
src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h

@@ -61,6 +61,10 @@ class FakeResolverResponseGenerator
   // returning a null result with no error).
   // returning a null result with no error).
   void SetFailure();
   void SetFailure();
 
 
+  // Same as SetFailure(), but instead of returning the error
+  // immediately, waits for the next call to RequestReresolutionLocked().
+  void SetFailureOnReresolution();
+
   // Returns a channel arg containing \a generator.
   // Returns a channel arg containing \a generator.
   static grpc_arg MakeChannelArg(FakeResolverResponseGenerator* generator);
   static grpc_arg MakeChannelArg(FakeResolverResponseGenerator* generator);
 
 

+ 384 - 0
src/core/ext/filters/client_channel/resolver_result_parsing.cc

@@ -0,0 +1,384 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#include "src/core/ext/filters/client_channel/resolver_result_parsing.h"
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/ext/filters/client_channel/client_channel.h"
+#include "src/core/ext/filters/client_channel/lb_policy_registry.h"
+#include "src/core/lib/channel/status_util.h"
+#include "src/core/lib/gpr/string.h"
+#include "src/core/lib/gprpp/memory.h"
+
+// As per the retry design, we do not allow more than 5 retry attempts.
+#define MAX_MAX_RETRY_ATTEMPTS 5
+
+namespace grpc_core {
+namespace internal {
+
+namespace {
+
+// Converts string format from JSON to proto.
+grpc_core::UniquePtr<char> ConvertCamelToSnake(const char* camel) {
+  const size_t size = strlen(camel);
+  char* snake = static_cast<char*>(gpr_malloc(size * 2));
+  size_t j = 0;
+  for (size_t i = 0; i < size; ++i) {
+    if (isupper(camel[i])) {
+      snake[j++] = '_';
+      snake[j++] = tolower(camel[i]);
+    } else {
+      snake[j++] = camel[i];
+    }
+  }
+  snake[j] = '\0';
+  return grpc_core::UniquePtr<char>(snake);
+}
+
+}  // namespace
+
+ProcessedResolverResult::ProcessedResolverResult(
+    const grpc_channel_args* resolver_result, bool parse_retry) {
+  ProcessServiceConfig(resolver_result, parse_retry);
+  // If no LB config was found above, just find the LB policy name then.
+  if (lb_policy_config_ == nullptr) ProcessLbPolicyName(resolver_result);
+}
+
+void ProcessedResolverResult::ProcessServiceConfig(
+    const grpc_channel_args* resolver_result, bool parse_retry) {
+  const grpc_arg* channel_arg =
+      grpc_channel_args_find(resolver_result, GRPC_ARG_SERVICE_CONFIG);
+  const char* service_config_json = grpc_channel_arg_get_string(channel_arg);
+  if (service_config_json != nullptr) {
+    service_config_json_.reset(gpr_strdup(service_config_json));
+    service_config_ = grpc_core::ServiceConfig::Create(service_config_json);
+    if (service_config_ != nullptr) {
+      if (parse_retry) {
+        channel_arg =
+            grpc_channel_args_find(resolver_result, GRPC_ARG_SERVER_URI);
+        const char* server_uri = grpc_channel_arg_get_string(channel_arg);
+        GPR_ASSERT(server_uri != nullptr);
+        grpc_uri* uri = grpc_uri_parse(server_uri, true);
+        GPR_ASSERT(uri->path[0] != '\0');
+        server_name_ = uri->path[0] == '/' ? uri->path + 1 : uri->path;
+        service_config_->ParseGlobalParams(ParseServiceConfig, this);
+        grpc_uri_destroy(uri);
+      } else {
+        service_config_->ParseGlobalParams(ParseServiceConfig, this);
+      }
+      method_params_table_ = service_config_->CreateMethodConfigTable(
+          ClientChannelMethodParams::CreateFromJson);
+    }
+  }
+}
+
+void ProcessedResolverResult::ProcessLbPolicyName(
+    const grpc_channel_args* resolver_result) {
+  const char* lb_policy_name = nullptr;
+  // Prefer the LB policy name found in the service config. Note that this is
+  // checking the deprecated loadBalancingPolicy field, rather than the new
+  // loadBalancingConfig field.
+  if (service_config_ != nullptr) {
+    lb_policy_name = service_config_->GetLoadBalancingPolicyName();
+  }
+  // Otherwise, find the LB policy name set by the client API.
+  if (lb_policy_name == nullptr) {
+    const grpc_arg* channel_arg =
+        grpc_channel_args_find(resolver_result, GRPC_ARG_LB_POLICY_NAME);
+    lb_policy_name = grpc_channel_arg_get_string(channel_arg);
+  }
+  // Special case: If at least one balancer address is present, we use
+  // the grpclb policy, regardless of what the resolver has returned.
+  const grpc_arg* channel_arg =
+      grpc_channel_args_find(resolver_result, GRPC_ARG_LB_ADDRESSES);
+  if (channel_arg != nullptr && channel_arg->type == GRPC_ARG_POINTER) {
+    grpc_lb_addresses* addresses =
+        static_cast<grpc_lb_addresses*>(channel_arg->value.pointer.p);
+    if (grpc_lb_addresses_contains_balancer_address(*addresses)) {
+      if (lb_policy_name != nullptr &&
+          gpr_stricmp(lb_policy_name, "grpclb") != 0) {
+        gpr_log(GPR_INFO,
+                "resolver requested LB policy %s but provided at least one "
+                "balancer address -- forcing use of grpclb LB policy",
+                lb_policy_name);
+      }
+      lb_policy_name = "grpclb";
+    }
+  }
+  // Use pick_first if nothing was specified and we didn't select grpclb
+  // above.
+  if (lb_policy_name == nullptr) lb_policy_name = "pick_first";
+  lb_policy_name_.reset(gpr_strdup(lb_policy_name));
+}
+
+void ProcessedResolverResult::ParseServiceConfig(
+    const grpc_json* field, ProcessedResolverResult* parsing_state) {
+  parsing_state->ParseLbConfigFromServiceConfig(field);
+  if (parsing_state->server_name_ != nullptr) {
+    parsing_state->ParseRetryThrottleParamsFromServiceConfig(field);
+  }
+}
+
+void ProcessedResolverResult::ParseLbConfigFromServiceConfig(
+    const grpc_json* field) {
+  if (lb_policy_config_ != nullptr) return;  // Already found.
+  // Find the LB config global parameter.
+  if (field->key == nullptr || strcmp(field->key, "loadBalancingConfig") != 0 ||
+      field->type != GRPC_JSON_ARRAY) {
+    return;  // Not valid lb config array.
+  }
+  // Find the first LB policy that this client supports.
+  for (grpc_json* lb_config = field->child; lb_config != nullptr;
+       lb_config = lb_config->next) {
+    if (lb_config->type != GRPC_JSON_OBJECT) return;
+    // Find the policy object.
+    grpc_json* policy = nullptr;
+    for (grpc_json* field = lb_config->child; field != nullptr;
+         field = field->next) {
+      if (field->key == nullptr || strcmp(field->key, "policy") != 0 ||
+          field->type != GRPC_JSON_OBJECT) {
+        return;
+      }
+      if (policy != nullptr) return;  // Duplicate.
+      policy = field;
+    }
+    // Find the specific policy content since the policy object is of type
+    // "oneof".
+    grpc_json* policy_content = nullptr;
+    for (grpc_json* field = policy->child; field != nullptr;
+         field = field->next) {
+      if (field->key == nullptr || field->type != GRPC_JSON_OBJECT) return;
+      if (policy_content != nullptr) return;  // Violate "oneof" type.
+      policy_content = field;
+    }
+    grpc_core::UniquePtr<char> lb_policy_name =
+        ConvertCamelToSnake(policy_content->key);
+    if (!grpc_core::LoadBalancingPolicyRegistry::LoadBalancingPolicyExists(
+            lb_policy_name.get())) {
+      continue;
+    }
+    lb_policy_name_ = std::move(lb_policy_name);
+    lb_policy_config_ = policy_content->child;
+    return;
+  }
+}
+
+void ProcessedResolverResult::ParseRetryThrottleParamsFromServiceConfig(
+    const grpc_json* field) {
+  if (strcmp(field->key, "retryThrottling") == 0) {
+    if (retry_throttle_data_ != nullptr) return;  // Duplicate.
+    if (field->type != GRPC_JSON_OBJECT) return;
+    int max_milli_tokens = 0;
+    int milli_token_ratio = 0;
+    for (grpc_json* sub_field = field->child; sub_field != nullptr;
+         sub_field = sub_field->next) {
+      if (sub_field->key == nullptr) return;
+      if (strcmp(sub_field->key, "maxTokens") == 0) {
+        if (max_milli_tokens != 0) return;  // Duplicate.
+        if (sub_field->type != GRPC_JSON_NUMBER) return;
+        max_milli_tokens = gpr_parse_nonnegative_int(sub_field->value);
+        if (max_milli_tokens == -1) return;
+        max_milli_tokens *= 1000;
+      } else if (strcmp(sub_field->key, "tokenRatio") == 0) {
+        if (milli_token_ratio != 0) return;  // Duplicate.
+        if (sub_field->type != GRPC_JSON_NUMBER) return;
+        // We support up to 3 decimal digits.
+        size_t whole_len = strlen(sub_field->value);
+        uint32_t multiplier = 1;
+        uint32_t decimal_value = 0;
+        const char* decimal_point = strchr(sub_field->value, '.');
+        if (decimal_point != nullptr) {
+          whole_len = static_cast<size_t>(decimal_point - sub_field->value);
+          multiplier = 1000;
+          size_t decimal_len = strlen(decimal_point + 1);
+          if (decimal_len > 3) decimal_len = 3;
+          if (!gpr_parse_bytes_to_uint32(decimal_point + 1, decimal_len,
+                                         &decimal_value)) {
+            return;
+          }
+          uint32_t decimal_multiplier = 1;
+          for (size_t i = 0; i < (3 - decimal_len); ++i) {
+            decimal_multiplier *= 10;
+          }
+          decimal_value *= decimal_multiplier;
+        }
+        uint32_t whole_value;
+        if (!gpr_parse_bytes_to_uint32(sub_field->value, whole_len,
+                                       &whole_value)) {
+          return;
+        }
+        milli_token_ratio =
+            static_cast<int>((whole_value * multiplier) + decimal_value);
+        if (milli_token_ratio <= 0) return;
+      }
+    }
+    retry_throttle_data_ =
+        grpc_core::internal::ServerRetryThrottleMap::GetDataForServer(
+            server_name_, max_milli_tokens, milli_token_ratio);
+  }
+}
+
+namespace {
+
+bool ParseWaitForReady(
+    grpc_json* field, ClientChannelMethodParams::WaitForReady* wait_for_ready) {
+  if (field->type != GRPC_JSON_TRUE && field->type != GRPC_JSON_FALSE) {
+    return false;
+  }
+  *wait_for_ready = field->type == GRPC_JSON_TRUE
+                        ? ClientChannelMethodParams::WAIT_FOR_READY_TRUE
+                        : ClientChannelMethodParams::WAIT_FOR_READY_FALSE;
+  return true;
+}
+
+// Parses a JSON field of the form generated for a google.proto.Duration
+// proto message, as per:
+//   https://developers.google.com/protocol-buffers/docs/proto3#json
+bool ParseDuration(grpc_json* field, grpc_millis* duration) {
+  if (field->type != GRPC_JSON_STRING) return false;
+  size_t len = strlen(field->value);
+  if (field->value[len - 1] != 's') return false;
+  UniquePtr<char> buf(gpr_strdup(field->value));
+  *(buf.get() + len - 1) = '\0';  // Remove trailing 's'.
+  char* decimal_point = strchr(buf.get(), '.');
+  int nanos = 0;
+  if (decimal_point != nullptr) {
+    *decimal_point = '\0';
+    nanos = gpr_parse_nonnegative_int(decimal_point + 1);
+    if (nanos == -1) {
+      return false;
+    }
+    int num_digits = static_cast<int>(strlen(decimal_point + 1));
+    if (num_digits > 9) {  // We don't accept greater precision than nanos.
+      return false;
+    }
+    for (int i = 0; i < (9 - num_digits); ++i) {
+      nanos *= 10;
+    }
+  }
+  int seconds =
+      decimal_point == buf.get() ? 0 : gpr_parse_nonnegative_int(buf.get());
+  if (seconds == -1) return false;
+  *duration = seconds * GPR_MS_PER_SEC + nanos / GPR_NS_PER_MS;
+  return true;
+}
+
+UniquePtr<ClientChannelMethodParams::RetryPolicy> ParseRetryPolicy(
+    grpc_json* field) {
+  auto retry_policy = MakeUnique<ClientChannelMethodParams::RetryPolicy>();
+  if (field->type != GRPC_JSON_OBJECT) return nullptr;
+  for (grpc_json* sub_field = field->child; sub_field != nullptr;
+       sub_field = sub_field->next) {
+    if (sub_field->key == nullptr) return nullptr;
+    if (strcmp(sub_field->key, "maxAttempts") == 0) {
+      if (retry_policy->max_attempts != 0) return nullptr;  // Duplicate.
+      if (sub_field->type != GRPC_JSON_NUMBER) return nullptr;
+      retry_policy->max_attempts = gpr_parse_nonnegative_int(sub_field->value);
+      if (retry_policy->max_attempts <= 1) return nullptr;
+      if (retry_policy->max_attempts > MAX_MAX_RETRY_ATTEMPTS) {
+        gpr_log(GPR_ERROR,
+                "service config: clamped retryPolicy.maxAttempts at %d",
+                MAX_MAX_RETRY_ATTEMPTS);
+        retry_policy->max_attempts = MAX_MAX_RETRY_ATTEMPTS;
+      }
+    } else if (strcmp(sub_field->key, "initialBackoff") == 0) {
+      if (retry_policy->initial_backoff > 0) return nullptr;  // Duplicate.
+      if (!ParseDuration(sub_field, &retry_policy->initial_backoff)) {
+        return nullptr;
+      }
+      if (retry_policy->initial_backoff == 0) return nullptr;
+    } else if (strcmp(sub_field->key, "maxBackoff") == 0) {
+      if (retry_policy->max_backoff > 0) return nullptr;  // Duplicate.
+      if (!ParseDuration(sub_field, &retry_policy->max_backoff)) {
+        return nullptr;
+      }
+      if (retry_policy->max_backoff == 0) return nullptr;
+    } else if (strcmp(sub_field->key, "backoffMultiplier") == 0) {
+      if (retry_policy->backoff_multiplier != 0) return nullptr;  // Duplicate.
+      if (sub_field->type != GRPC_JSON_NUMBER) return nullptr;
+      if (sscanf(sub_field->value, "%f", &retry_policy->backoff_multiplier) !=
+          1) {
+        return nullptr;
+      }
+      if (retry_policy->backoff_multiplier <= 0) return nullptr;
+    } else if (strcmp(sub_field->key, "retryableStatusCodes") == 0) {
+      if (!retry_policy->retryable_status_codes.Empty()) {
+        return nullptr;  // Duplicate.
+      }
+      if (sub_field->type != GRPC_JSON_ARRAY) return nullptr;
+      for (grpc_json* element = sub_field->child; element != nullptr;
+           element = element->next) {
+        if (element->type != GRPC_JSON_STRING) return nullptr;
+        grpc_status_code status;
+        if (!grpc_status_code_from_string(element->value, &status)) {
+          return nullptr;
+        }
+        retry_policy->retryable_status_codes.Add(status);
+      }
+      if (retry_policy->retryable_status_codes.Empty()) return nullptr;
+    }
+  }
+  // Make sure required fields are set.
+  if (retry_policy->max_attempts == 0 || retry_policy->initial_backoff == 0 ||
+      retry_policy->max_backoff == 0 || retry_policy->backoff_multiplier == 0 ||
+      retry_policy->retryable_status_codes.Empty()) {
+    return nullptr;
+  }
+  return retry_policy;
+}
+
+}  // namespace
+
+RefCountedPtr<ClientChannelMethodParams>
+ClientChannelMethodParams::CreateFromJson(const grpc_json* json) {
+  RefCountedPtr<ClientChannelMethodParams> method_params =
+      MakeRefCounted<ClientChannelMethodParams>();
+  for (grpc_json* field = json->child; field != nullptr; field = field->next) {
+    if (field->key == nullptr) continue;
+    if (strcmp(field->key, "waitForReady") == 0) {
+      if (method_params->wait_for_ready_ != WAIT_FOR_READY_UNSET) {
+        return nullptr;  // Duplicate.
+      }
+      if (!ParseWaitForReady(field, &method_params->wait_for_ready_)) {
+        return nullptr;
+      }
+    } else if (strcmp(field->key, "timeout") == 0) {
+      if (method_params->timeout_ > 0) return nullptr;  // Duplicate.
+      if (!ParseDuration(field, &method_params->timeout_)) return nullptr;
+    } else if (strcmp(field->key, "retryPolicy") == 0) {
+      if (method_params->retry_policy_ != nullptr) {
+        return nullptr;  // Duplicate.
+      }
+      method_params->retry_policy_ = ParseRetryPolicy(field);
+      if (method_params->retry_policy_ == nullptr) return nullptr;
+    }
+  }
+  return method_params;
+}
+
+}  // namespace internal
+}  // namespace grpc_core

+ 146 - 0
src/core/ext/filters/client_channel/resolver_result_parsing.h

@@ -0,0 +1,146 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_RESULT_PARSING_H
+#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_RESULT_PARSING_H
+
+#include <grpc/support/port_platform.h>
+
+#include "src/core/ext/filters/client_channel/retry_throttle.h"
+#include "src/core/lib/channel/status_util.h"
+#include "src/core/lib/gprpp/ref_counted.h"
+#include "src/core/lib/gprpp/ref_counted_ptr.h"
+#include "src/core/lib/iomgr/exec_ctx.h"  // for grpc_millis
+#include "src/core/lib/json/json.h"
+#include "src/core/lib/slice/slice_hash_table.h"
+#include "src/core/lib/transport/service_config.h"
+
+namespace grpc_core {
+namespace internal {
+
+class ClientChannelMethodParams;
+
+// A table mapping from a method name to its method parameters.
+typedef grpc_core::SliceHashTable<
+    grpc_core::RefCountedPtr<ClientChannelMethodParams>>
+    ClientChannelMethodParamsTable;
+
+// A container of processed fields from the resolver result. Simplifies the
+// usage of resolver result.
+class ProcessedResolverResult {
+ public:
+  // Processes the resolver result and populates the relative members
+  // for later consumption. Tries to parse retry parameters only if parse_retry
+  // is true.
+  ProcessedResolverResult(const grpc_channel_args* resolver_result,
+                          bool parse_retry);
+
+  // Getters. Any managed object's ownership is transferred.
+  grpc_core::UniquePtr<char> service_config_json() {
+    return std::move(service_config_json_);
+  }
+  grpc_core::RefCountedPtr<ServerRetryThrottleData> retry_throttle_data() {
+    return std::move(retry_throttle_data_);
+  }
+  grpc_core::RefCountedPtr<ClientChannelMethodParamsTable>
+  method_params_table() {
+    return std::move(method_params_table_);
+  }
+  grpc_core::UniquePtr<char> lb_policy_name() {
+    return std::move(lb_policy_name_);
+  }
+  grpc_json* lb_policy_config() { return lb_policy_config_; }
+
+ private:
+  // Finds the service config; extracts LB config and (maybe) retry throttle
+  // params from it.
+  void ProcessServiceConfig(const grpc_channel_args* resolver_result,
+                            bool parse_retry);
+
+  // Finds the LB policy name (when no LB config was found).
+  void ProcessLbPolicyName(const grpc_channel_args* resolver_result);
+
+  // Parses the service config. Intended to be used by
+  // ServiceConfig::ParseGlobalParams.
+  static void ParseServiceConfig(const grpc_json* field,
+                                 ProcessedResolverResult* parsing_state);
+  // Parses the LB config from service config.
+  void ParseLbConfigFromServiceConfig(const grpc_json* field);
+  // Parses the retry throttle parameters from service config.
+  void ParseRetryThrottleParamsFromServiceConfig(const grpc_json* field);
+
+  // Service config.
+  grpc_core::UniquePtr<char> service_config_json_;
+  grpc_core::UniquePtr<grpc_core::ServiceConfig> service_config_;
+  // LB policy.
+  grpc_json* lb_policy_config_ = nullptr;
+  grpc_core::UniquePtr<char> lb_policy_name_;
+  // Retry throttle data.
+  char* server_name_ = nullptr;
+  grpc_core::RefCountedPtr<ServerRetryThrottleData> retry_throttle_data_;
+  // Method params table.
+  grpc_core::RefCountedPtr<ClientChannelMethodParamsTable> method_params_table_;
+};
+
+// The parameters of a method.
+class ClientChannelMethodParams : public RefCounted<ClientChannelMethodParams> {
+ public:
+  enum WaitForReady {
+    WAIT_FOR_READY_UNSET = 0,
+    WAIT_FOR_READY_FALSE,
+    WAIT_FOR_READY_TRUE
+  };
+
+  struct RetryPolicy {
+    int max_attempts = 0;
+    grpc_millis initial_backoff = 0;
+    grpc_millis max_backoff = 0;
+    float backoff_multiplier = 0;
+    StatusCodeSet retryable_status_codes;
+  };
+
+  /// Creates a method_parameters object from \a json.
+  /// Intended for use with ServiceConfig::CreateMethodConfigTable().
+  static RefCountedPtr<ClientChannelMethodParams> CreateFromJson(
+      const grpc_json* json);
+
+  grpc_millis timeout() const { return timeout_; }
+  WaitForReady wait_for_ready() const { return wait_for_ready_; }
+  const RetryPolicy* retry_policy() const { return retry_policy_.get(); }
+
+ private:
+  // So New() can call our private ctor.
+  template <typename T, typename... Args>
+  friend T* grpc_core::New(Args&&... args);
+
+  // So Delete() can call our private dtor.
+  template <typename T>
+  friend void grpc_core::Delete(T*);
+
+  ClientChannelMethodParams() {}
+  virtual ~ClientChannelMethodParams() {}
+
+  grpc_millis timeout_ = 0;
+  WaitForReady wait_for_ready_ = WAIT_FOR_READY_UNSET;
+  UniquePtr<RetryPolicy> retry_policy_;
+};
+
+}  // namespace internal
+}  // namespace grpc_core
+
+#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_RESULT_PARSING_H */

+ 57 - 16
src/core/lib/gprpp/ref_counted.h

@@ -24,6 +24,8 @@
 #include <grpc/support/log.h>
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/sync.h>
 
 
+#include <atomic>
+#include <cassert>
 #include <cinttypes>
 #include <cinttypes>
 
 
 #include "src/core/lib/debug/trace.h"
 #include "src/core/lib/debug/trace.h"
@@ -42,7 +44,7 @@ class PolymorphicRefCount {
  protected:
  protected:
   GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE
   GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE
 
 
-  virtual ~PolymorphicRefCount() {}
+  virtual ~PolymorphicRefCount() = default;
 };
 };
 
 
 // NonPolymorphicRefCount does not enforce polymorphic destruction of
 // NonPolymorphicRefCount does not enforce polymorphic destruction of
@@ -55,7 +57,48 @@ class NonPolymorphicRefCount {
  protected:
  protected:
   GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE
   GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE
 
 
-  ~NonPolymorphicRefCount() {}
+  ~NonPolymorphicRefCount() = default;
+};
+
+// RefCount is a simple atomic ref-count.
+//
+// This is a C++ implementation of gpr_refcount, with inline functions. Due to
+// inline functions, this class is significantly more efficient than
+// gpr_refcount and should be preferred over gpr_refcount whenever possible.
+//
+// TODO(soheil): Remove gpr_refcount after submitting the GRFC and the paragraph
+//               above.
+class RefCount {
+ public:
+  using Value = intptr_t;
+
+  // `init` is the initial refcount stored in this object.
+  constexpr explicit RefCount(Value init = 1) : value_(init) {}
+
+  // Increases the ref-count by `n`.
+  void Ref(Value n = 1) { value_.fetch_add(n, std::memory_order_relaxed); }
+
+  // Similar to Ref() with an assert on the ref-count being non-zero.
+  void RefNonZero() {
+#ifndef NDEBUG
+    const Value prior = value_.fetch_add(1, std::memory_order_relaxed);
+    assert(prior > 0);
+#else
+    Ref();
+#endif
+  }
+
+  // Decrements the ref-count and returns true if the ref-count reaches 0.
+  bool Unref() {
+    const Value prior = value_.fetch_sub(1, std::memory_order_acq_rel);
+    GPR_DEBUG_ASSERT(prior > 0);
+    return prior == 1;
+  }
+
+  Value get() const { return value_.load(std::memory_order_relaxed); }
+
+ private:
+  std::atomic<Value> value_;
 };
 };
 
 
 // A base class for reference-counted objects.
 // A base class for reference-counted objects.
@@ -97,7 +140,7 @@ class RefCounted : public Impl {
   // private, since it will only be used by RefCountedPtr<>, which is a
   // private, since it will only be used by RefCountedPtr<>, which is a
   // friend of this class.
   // friend of this class.
   void Unref() {
   void Unref() {
-    if (gpr_unref(&refs_)) {
+    if (refs_.Unref()) {
       Delete(static_cast<Child*>(this));
       Delete(static_cast<Child*>(this));
     }
     }
   }
   }
@@ -111,19 +154,19 @@ class RefCounted : public Impl {
  protected:
  protected:
   GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE
   GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE
 
 
-  RefCounted() { gpr_ref_init(&refs_, 1); }
+  RefCounted() = default;
 
 
   // Note: Depending on the Impl used, this dtor can be implicitly virtual.
   // Note: Depending on the Impl used, this dtor can be implicitly virtual.
-  ~RefCounted() {}
+  ~RefCounted() = default;
 
 
  private:
  private:
   // Allow RefCountedPtr<> to access IncrementRefCount().
   // Allow RefCountedPtr<> to access IncrementRefCount().
   template <typename T>
   template <typename T>
   friend class RefCountedPtr;
   friend class RefCountedPtr;
 
 
-  void IncrementRefCount() { gpr_ref(&refs_); }
+  void IncrementRefCount() { refs_.Ref(); }
 
 
-  gpr_refcount refs_;
+  RefCount refs_;
 };
 };
 
 
 // An alternative version of the RefCounted base class that
 // An alternative version of the RefCounted base class that
@@ -143,7 +186,7 @@ class RefCountedWithTracing : public Impl {
   RefCountedPtr<Child> Ref(const DebugLocation& location,
   RefCountedPtr<Child> Ref(const DebugLocation& location,
                            const char* reason) GRPC_MUST_USE_RESULT {
                            const char* reason) GRPC_MUST_USE_RESULT {
     if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) {
     if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) {
-      gpr_atm old_refs = gpr_atm_no_barrier_load(&refs_.count);
+      const RefCount::Value old_refs = refs_.get();
       gpr_log(GPR_INFO, "%s:%p %s:%d ref %" PRIdPTR " -> %" PRIdPTR " %s",
       gpr_log(GPR_INFO, "%s:%p %s:%d ref %" PRIdPTR " -> %" PRIdPTR " %s",
               trace_flag_->name(), this, location.file(), location.line(),
               trace_flag_->name(), this, location.file(), location.line(),
               old_refs, old_refs + 1, reason);
               old_refs, old_refs + 1, reason);
@@ -157,14 +200,14 @@ class RefCountedWithTracing : public Impl {
   // friend of this class.
   // friend of this class.
 
 
   void Unref() {
   void Unref() {
-    if (gpr_unref(&refs_)) {
+    if (refs_.Unref()) {
       Delete(static_cast<Child*>(this));
       Delete(static_cast<Child*>(this));
     }
     }
   }
   }
 
 
   void Unref(const DebugLocation& location, const char* reason) {
   void Unref(const DebugLocation& location, const char* reason) {
     if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) {
     if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) {
-      gpr_atm old_refs = gpr_atm_no_barrier_load(&refs_.count);
+      const RefCount::Value old_refs = refs_.get();
       gpr_log(GPR_INFO, "%s:%p %s:%d unref %" PRIdPTR " -> %" PRIdPTR " %s",
       gpr_log(GPR_INFO, "%s:%p %s:%d unref %" PRIdPTR " -> %" PRIdPTR " %s",
               trace_flag_->name(), this, location.file(), location.line(),
               trace_flag_->name(), this, location.file(), location.line(),
               old_refs, old_refs - 1, reason);
               old_refs, old_refs - 1, reason);
@@ -185,9 +228,7 @@ class RefCountedWithTracing : public Impl {
       : RefCountedWithTracing(static_cast<TraceFlag*>(nullptr)) {}
       : RefCountedWithTracing(static_cast<TraceFlag*>(nullptr)) {}
 
 
   explicit RefCountedWithTracing(TraceFlag* trace_flag)
   explicit RefCountedWithTracing(TraceFlag* trace_flag)
-      : trace_flag_(trace_flag) {
-    gpr_ref_init(&refs_, 1);
-  }
+      : trace_flag_(trace_flag) {}
 
 
 #ifdef NDEBUG
 #ifdef NDEBUG
   explicit RefCountedWithTracing(DebugOnlyTraceFlag* trace_flag)
   explicit RefCountedWithTracing(DebugOnlyTraceFlag* trace_flag)
@@ -195,17 +236,17 @@ class RefCountedWithTracing : public Impl {
 #endif
 #endif
 
 
   // Note: Depending on the Impl used, this dtor can be implicitly virtual.
   // Note: Depending on the Impl used, this dtor can be implicitly virtual.
-  ~RefCountedWithTracing() {}
+  ~RefCountedWithTracing() = default;
 
 
  private:
  private:
   // Allow RefCountedPtr<> to access IncrementRefCount().
   // Allow RefCountedPtr<> to access IncrementRefCount().
   template <typename T>
   template <typename T>
   friend class RefCountedPtr;
   friend class RefCountedPtr;
 
 
-  void IncrementRefCount() { gpr_ref(&refs_); }
+  void IncrementRefCount() { refs_.Ref(); }
 
 
   TraceFlag* trace_flag_ = nullptr;
   TraceFlag* trace_flag_ = nullptr;
-  gpr_refcount refs_;
+  RefCount refs_;
 };
 };
 
 
 }  // namespace grpc_core
 }  // namespace grpc_core

+ 1 - 1
src/core/lib/surface/version.cc

@@ -25,4 +25,4 @@
 
 
 const char* grpc_version_string(void) { return "7.0.0-dev"; }
 const char* grpc_version_string(void) { return "7.0.0-dev"; }
 
 
-const char* grpc_g_stands_for(void) { return "gizmo"; }
+const char* grpc_g_stands_for(void) { return "goose"; }

+ 3 - 5
src/cpp/client/channel_cc.cc

@@ -54,13 +54,11 @@ namespace grpc {
 static internal::GrpcLibraryInitializer g_gli_initializer;
 static internal::GrpcLibraryInitializer g_gli_initializer;
 Channel::Channel(
 Channel::Channel(
     const grpc::string& host, grpc_channel* channel,
     const grpc::string& host, grpc_channel* channel,
-    std::unique_ptr<std::vector<
-        std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>>
+    std::vector<
+        std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
         interceptor_creators)
         interceptor_creators)
     : host_(host), c_channel_(channel) {
     : host_(host), c_channel_(channel) {
-  if (interceptor_creators != nullptr) {
-    interceptor_creators_ = std::move(*interceptor_creators);
-  }
+  interceptor_creators_ = std::move(interceptor_creators);
   g_gli_initializer.summon();
   g_gli_initializer.summon();
 }
 }
 
 

+ 5 - 4
src/cpp/client/client_context.cc

@@ -41,9 +41,10 @@ class DefaultGlobalClientCallbacks final
 };
 };
 
 
 static internal::GrpcLibraryInitializer g_gli_initializer;
 static internal::GrpcLibraryInitializer g_gli_initializer;
-static DefaultGlobalClientCallbacks g_default_client_callbacks;
+static DefaultGlobalClientCallbacks* g_default_client_callbacks =
+    new DefaultGlobalClientCallbacks();
 static ClientContext::GlobalCallbacks* g_client_callbacks =
 static ClientContext::GlobalCallbacks* g_client_callbacks =
-    &g_default_client_callbacks;
+    g_default_client_callbacks;
 
 
 ClientContext::ClientContext()
 ClientContext::ClientContext()
     : initial_metadata_received_(false),
     : initial_metadata_received_(false),
@@ -139,9 +140,9 @@ grpc::string ClientContext::peer() const {
 }
 }
 
 
 void ClientContext::SetGlobalCallbacks(GlobalCallbacks* client_callbacks) {
 void ClientContext::SetGlobalCallbacks(GlobalCallbacks* client_callbacks) {
-  GPR_ASSERT(g_client_callbacks == &g_default_client_callbacks);
+  GPR_ASSERT(g_client_callbacks == g_default_client_callbacks);
   GPR_ASSERT(client_callbacks != nullptr);
   GPR_ASSERT(client_callbacks != nullptr);
-  GPR_ASSERT(client_callbacks != &g_default_client_callbacks);
+  GPR_ASSERT(client_callbacks != g_default_client_callbacks);
   g_client_callbacks = client_callbacks;
   g_client_callbacks = client_callbacks;
 }
 }
 
 

+ 19 - 17
src/cpp/client/create_channel.cc

@@ -39,13 +39,14 @@ std::shared_ptr<Channel> CreateCustomChannel(
     const std::shared_ptr<ChannelCredentials>& creds,
     const std::shared_ptr<ChannelCredentials>& creds,
     const ChannelArguments& args) {
     const ChannelArguments& args) {
   GrpcLibraryCodegen init_lib;  // We need to call init in case of a bad creds.
   GrpcLibraryCodegen init_lib;  // We need to call init in case of a bad creds.
-  return creds
-             ? creds->CreateChannel(target, args)
-             : CreateChannelInternal("",
-                                     grpc_lame_client_channel_create(
-                                         nullptr, GRPC_STATUS_INVALID_ARGUMENT,
-                                         "Invalid credentials."),
-                                     nullptr);
+  return creds ? creds->CreateChannel(target, args)
+               : CreateChannelInternal(
+                     "",
+                     grpc_lame_client_channel_create(
+                         nullptr, GRPC_STATUS_INVALID_ARGUMENT,
+                         "Invalid credentials."),
+                     std::vector<std::unique_ptr<
+                         experimental::ClientInterceptorFactoryInterface>>());
 }
 }
 
 
 namespace experimental {
 namespace experimental {
@@ -64,17 +65,18 @@ std::shared_ptr<Channel> CreateCustomChannelWithInterceptors(
     const grpc::string& target,
     const grpc::string& target,
     const std::shared_ptr<ChannelCredentials>& creds,
     const std::shared_ptr<ChannelCredentials>& creds,
     const ChannelArguments& args,
     const ChannelArguments& args,
-    std::unique_ptr<std::vector<
-        std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>>
+    std::vector<
+        std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
         interceptor_creators) {
         interceptor_creators) {
-  return creds
-             ? creds->CreateChannelWithInterceptors(
-                   target, args, std::move(interceptor_creators))
-             : CreateChannelInternal("",
-                                     grpc_lame_client_channel_create(
-                                         nullptr, GRPC_STATUS_INVALID_ARGUMENT,
-                                         "Invalid credentials."),
-                                     nullptr);
+  return creds ? creds->CreateChannelWithInterceptors(
+                     target, args, std::move(interceptor_creators))
+               : CreateChannelInternal(
+                     "",
+                     grpc_lame_client_channel_create(
+                         nullptr, GRPC_STATUS_INVALID_ARGUMENT,
+                         "Invalid credentials."),
+                     std::vector<std::unique_ptr<
+                         experimental::ClientInterceptorFactoryInterface>>());
 }
 }
 }  // namespace experimental
 }  // namespace experimental
 
 

+ 2 - 2
src/cpp/client/create_channel_internal.cc

@@ -26,8 +26,8 @@ namespace grpc {
 
 
 std::shared_ptr<Channel> CreateChannelInternal(
 std::shared_ptr<Channel> CreateChannelInternal(
     const grpc::string& host, grpc_channel* c_channel,
     const grpc::string& host, grpc_channel* c_channel,
-    std::unique_ptr<std::vector<
-        std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>>
+    std::vector<
+        std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
         interceptor_creators) {
         interceptor_creators) {
   return std::shared_ptr<Channel>(
   return std::shared_ptr<Channel>(
       new Channel(host, c_channel, std::move(interceptor_creators)));
       new Channel(host, c_channel, std::move(interceptor_creators)));

+ 2 - 2
src/cpp/client/create_channel_internal.h

@@ -31,8 +31,8 @@ class Channel;
 
 
 std::shared_ptr<Channel> CreateChannelInternal(
 std::shared_ptr<Channel> CreateChannelInternal(
     const grpc::string& host, grpc_channel* c_channel,
     const grpc::string& host, grpc_channel* c_channel,
-    std::unique_ptr<std::vector<
-        std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>>
+    std::vector<
+        std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
         interceptor_creators);
         interceptor_creators);
 
 
 }  // namespace grpc
 }  // namespace grpc

+ 6 - 4
src/cpp/client/create_channel_posix.cc

@@ -34,7 +34,8 @@ std::shared_ptr<Channel> CreateInsecureChannelFromFd(const grpc::string& target,
   init_lib.init();
   init_lib.init();
   return CreateChannelInternal(
   return CreateChannelInternal(
       "", grpc_insecure_channel_create_from_fd(target.c_str(), fd, nullptr),
       "", grpc_insecure_channel_create_from_fd(target.c_str(), fd, nullptr),
-      nullptr);
+      std::vector<
+          std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>());
 }
 }
 
 
 std::shared_ptr<Channel> CreateCustomInsecureChannelFromFd(
 std::shared_ptr<Channel> CreateCustomInsecureChannelFromFd(
@@ -46,15 +47,16 @@ std::shared_ptr<Channel> CreateCustomInsecureChannelFromFd(
   return CreateChannelInternal(
   return CreateChannelInternal(
       "",
       "",
       grpc_insecure_channel_create_from_fd(target.c_str(), fd, &channel_args),
       grpc_insecure_channel_create_from_fd(target.c_str(), fd, &channel_args),
-      nullptr);
+      std::vector<
+          std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>());
 }
 }
 
 
 namespace experimental {
 namespace experimental {
 
 
 std::shared_ptr<Channel> CreateCustomInsecureChannelWithInterceptorsFromFd(
 std::shared_ptr<Channel> CreateCustomInsecureChannelWithInterceptorsFromFd(
     const grpc::string& target, int fd, const ChannelArguments& args,
     const grpc::string& target, int fd, const ChannelArguments& args,
-    std::unique_ptr<std::vector<
-        std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>>
+    std::vector<
+        std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
         interceptor_creators) {
         interceptor_creators) {
   internal::GrpcLibrary init_lib;
   internal::GrpcLibrary init_lib;
   init_lib.init();
   init_lib.init();

+ 6 - 3
src/cpp/client/cronet_credentials.cc

@@ -31,7 +31,10 @@ class CronetChannelCredentialsImpl final : public ChannelCredentials {
 
 
   std::shared_ptr<grpc::Channel> CreateChannel(
   std::shared_ptr<grpc::Channel> CreateChannel(
       const string& target, const grpc::ChannelArguments& args) override {
       const string& target, const grpc::ChannelArguments& args) override {
-    return CreateChannelWithInterceptors(target, args, nullptr);
+    return CreateChannelWithInterceptors(
+        target, args,
+        std::vector<std::unique_ptr<
+            experimental::ClientInterceptorFactoryInterface>>());
   }
   }
 
 
   SecureChannelCredentials* AsSecureCredentials() override { return nullptr; }
   SecureChannelCredentials* AsSecureCredentials() override { return nullptr; }
@@ -39,8 +42,8 @@ class CronetChannelCredentialsImpl final : public ChannelCredentials {
  private:
  private:
   std::shared_ptr<grpc::Channel> CreateChannelWithInterceptors(
   std::shared_ptr<grpc::Channel> CreateChannelWithInterceptors(
       const string& target, const grpc::ChannelArguments& args,
       const string& target, const grpc::ChannelArguments& args,
-      std::unique_ptr<std::vector<
-          std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>>
+      std::vector<
+          std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
           interceptor_creators) override {
           interceptor_creators) override {
     grpc_channel_args channel_args;
     grpc_channel_args channel_args;
     args.SetChannelArgs(&channel_args);
     args.SetChannelArgs(&channel_args);

+ 6 - 3
src/cpp/client/insecure_credentials.cc

@@ -32,13 +32,16 @@ class InsecureChannelCredentialsImpl final : public ChannelCredentials {
  public:
  public:
   std::shared_ptr<grpc::Channel> CreateChannel(
   std::shared_ptr<grpc::Channel> CreateChannel(
       const string& target, const grpc::ChannelArguments& args) override {
       const string& target, const grpc::ChannelArguments& args) override {
-    return CreateChannelWithInterceptors(target, args, nullptr);
+    return CreateChannelWithInterceptors(
+        target, args,
+        std::vector<std::unique_ptr<
+            experimental::ClientInterceptorFactoryInterface>>());
   }
   }
 
 
   std::shared_ptr<grpc::Channel> CreateChannelWithInterceptors(
   std::shared_ptr<grpc::Channel> CreateChannelWithInterceptors(
       const string& target, const grpc::ChannelArguments& args,
       const string& target, const grpc::ChannelArguments& args,
-      std::unique_ptr<std::vector<
-          std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>>
+      std::vector<
+          std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
           interceptor_creators) override {
           interceptor_creators) override {
     grpc_channel_args channel_args;
     grpc_channel_args channel_args;
     args.SetChannelArgs(&channel_args);
     args.SetChannelArgs(&channel_args);

+ 6 - 3
src/cpp/client/secure_credentials.cc

@@ -36,14 +36,17 @@ SecureChannelCredentials::SecureChannelCredentials(
 
 
 std::shared_ptr<grpc::Channel> SecureChannelCredentials::CreateChannel(
 std::shared_ptr<grpc::Channel> SecureChannelCredentials::CreateChannel(
     const string& target, const grpc::ChannelArguments& args) {
     const string& target, const grpc::ChannelArguments& args) {
-  return CreateChannelWithInterceptors(target, args, nullptr);
+  return CreateChannelWithInterceptors(
+      target, args,
+      std::vector<
+          std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>());
 }
 }
 
 
 std::shared_ptr<grpc::Channel>
 std::shared_ptr<grpc::Channel>
 SecureChannelCredentials::CreateChannelWithInterceptors(
 SecureChannelCredentials::CreateChannelWithInterceptors(
     const string& target, const grpc::ChannelArguments& args,
     const string& target, const grpc::ChannelArguments& args,
-    std::unique_ptr<std::vector<
-        std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>>
+    std::vector<
+        std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
         interceptor_creators) {
         interceptor_creators) {
   grpc_channel_args channel_args;
   grpc_channel_args channel_args;
   args.SetChannelArgs(&channel_args);
   args.SetChannelArgs(&channel_args);

+ 2 - 2
src/cpp/client/secure_credentials.h

@@ -42,8 +42,8 @@ class SecureChannelCredentials final : public ChannelCredentials {
  private:
  private:
   std::shared_ptr<grpc::Channel> CreateChannelWithInterceptors(
   std::shared_ptr<grpc::Channel> CreateChannelWithInterceptors(
       const string& target, const grpc::ChannelArguments& args,
       const string& target, const grpc::ChannelArguments& args,
-      std::unique_ptr<std::vector<
-          std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>>
+      std::vector<
+          std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
           interceptor_creators) override;
           interceptor_creators) override;
   grpc_channel_credentials* const c_creds_;
   grpc_channel_credentials* const c_creds_;
 };
 };

+ 1 - 1
src/cpp/common/version_cc.cc

@@ -22,5 +22,5 @@
 #include <grpcpp/grpcpp.h>
 #include <grpcpp/grpcpp.h>
 
 
 namespace grpc {
 namespace grpc {
-grpc::string Version() { return "1.17.0-dev"; }
+grpc::string Version() { return "1.18.0-dev"; }
 }  // namespace grpc
 }  // namespace grpc

+ 5 - 7
src/cpp/server/server_cc.cc

@@ -84,10 +84,7 @@ class ShutdownTag : public internal::CompletionQueueTag {
 
 
 class DummyTag : public internal::CompletionQueueTag {
 class DummyTag : public internal::CompletionQueueTag {
  public:
  public:
-  bool FinalizeResult(void** tag, bool* status) {
-    *status = true;
-    return true;
-  }
+  bool FinalizeResult(void** tag, bool* status) { return true; }
 };
 };
 
 
 class UnimplementedAsyncRequestContext {
 class UnimplementedAsyncRequestContext {
@@ -732,14 +729,15 @@ std::shared_ptr<Channel> Server::InProcessChannel(
   grpc_channel_args channel_args = args.c_channel_args();
   grpc_channel_args channel_args = args.c_channel_args();
   return CreateChannelInternal(
   return CreateChannelInternal(
       "inproc", grpc_inproc_channel_create(server_, &channel_args, nullptr),
       "inproc", grpc_inproc_channel_create(server_, &channel_args, nullptr),
-      nullptr);
+      std::vector<
+          std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>());
 }
 }
 
 
 std::shared_ptr<Channel>
 std::shared_ptr<Channel>
 Server::experimental_type::InProcessChannelWithInterceptors(
 Server::experimental_type::InProcessChannelWithInterceptors(
     const ChannelArguments& args,
     const ChannelArguments& args,
-    std::unique_ptr<std::vector<
-        std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>>
+    std::vector<
+        std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
         interceptor_creators) {
         interceptor_creators) {
   grpc_channel_args channel_args = args.c_channel_args();
   grpc_channel_args channel_args = args.c_channel_args();
   return CreateChannelInternal(
   return CreateChannelInternal(

+ 1 - 1
src/csharp/Grpc.Core.Tests/Internal/AsyncCallServerTest.cs

@@ -49,7 +49,7 @@ namespace Grpc.Core.Internal.Tests
 
 
             fakeCall = new FakeNativeCall();
             fakeCall = new FakeNativeCall();
             asyncCallServer = new AsyncCallServer<string, string>(
             asyncCallServer = new AsyncCallServer<string, string>(
-                Marshallers.StringMarshaller.Serializer, Marshallers.StringMarshaller.Deserializer,
+                Marshallers.StringMarshaller.ContextualSerializer, Marshallers.StringMarshaller.ContextualDeserializer,
                 server);
                 server);
             asyncCallServer.InitializeForTesting(fakeCall);
             asyncCallServer.InitializeForTesting(fakeCall);
         }
         }

+ 2 - 5
src/csharp/Grpc.Core.Tests/MarshallerTest.cs

@@ -69,11 +69,8 @@ namespace Grpc.Core.Tests
 
 
             Assert.AreSame(contextualSerializer, marshaller.ContextualSerializer);
             Assert.AreSame(contextualSerializer, marshaller.ContextualSerializer);
             Assert.AreSame(contextualDeserializer, marshaller.ContextualDeserializer);
             Assert.AreSame(contextualDeserializer, marshaller.ContextualDeserializer);
-
-            // test that emulated serializer and deserializer work
-            var origMsg = "abc";
-            var serialized = marshaller.Serializer(origMsg);
-            Assert.AreEqual(origMsg, marshaller.Deserializer(serialized));
+            Assert.Throws(typeof(NotImplementedException), () => marshaller.Serializer("abc"));
+            Assert.Throws(typeof(NotImplementedException), () => marshaller.Deserializer(new byte[] {1, 2, 3}));
         }
         }
 
 
         class FakeSerializationContext : SerializationContext
         class FakeSerializationContext : SerializationContext

+ 6 - 1
src/csharp/Grpc.Core/DeserializationContext.cs

@@ -16,6 +16,8 @@
 
 
 #endregion
 #endregion
 
 
+using System;
+
 namespace Grpc.Core
 namespace Grpc.Core
 {
 {
     /// <summary>
     /// <summary>
@@ -41,6 +43,9 @@ namespace Grpc.Core
         /// (as there is no practical reason for doing so) and <c>DeserializationContext</c> implementations are free to assume so.
         /// (as there is no practical reason for doing so) and <c>DeserializationContext</c> implementations are free to assume so.
         /// </summary>
         /// </summary>
         /// <returns>byte array containing the entire payload.</returns>
         /// <returns>byte array containing the entire payload.</returns>
-        public abstract byte[] PayloadAsNewBuffer();
+        public virtual byte[] PayloadAsNewBuffer()
+        {
+            throw new NotImplementedException();
+        }
     }
     }
 }
 }

+ 1 - 1
src/csharp/Grpc.Core/Internal/AsyncCall.cs

@@ -54,7 +54,7 @@ namespace Grpc.Core.Internal
         ClientSideStatus? finishedStatus;
         ClientSideStatus? finishedStatus;
 
 
         public AsyncCall(CallInvocationDetails<TRequest, TResponse> callDetails)
         public AsyncCall(CallInvocationDetails<TRequest, TResponse> callDetails)
-            : base(callDetails.RequestMarshaller.Serializer, callDetails.ResponseMarshaller.Deserializer)
+            : base(callDetails.RequestMarshaller.ContextualSerializer, callDetails.ResponseMarshaller.ContextualDeserializer)
         {
         {
             this.details = callDetails.WithOptions(callDetails.Options.Normalize());
             this.details = callDetails.WithOptions(callDetails.Options.Normalize());
             this.initialMetadataSent = true;  // we always send metadata at the very beginning of the call.
             this.initialMetadataSent = true;  // we always send metadata at the very beginning of the call.

+ 22 - 5
src/csharp/Grpc.Core/Internal/AsyncCallBase.cs

@@ -40,8 +40,8 @@ namespace Grpc.Core.Internal
         static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<AsyncCallBase<TWrite, TRead>>();
         static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<AsyncCallBase<TWrite, TRead>>();
         protected static readonly Status DeserializeResponseFailureStatus = new Status(StatusCode.Internal, "Failed to deserialize response message.");
         protected static readonly Status DeserializeResponseFailureStatus = new Status(StatusCode.Internal, "Failed to deserialize response message.");
 
 
-        readonly Func<TWrite, byte[]> serializer;
-        readonly Func<byte[], TRead> deserializer;
+        readonly Action<TWrite, SerializationContext> serializer;
+        readonly Func<DeserializationContext, TRead> deserializer;
 
 
         protected readonly object myLock = new object();
         protected readonly object myLock = new object();
 
 
@@ -63,7 +63,7 @@ namespace Grpc.Core.Internal
         protected bool initialMetadataSent;
         protected bool initialMetadataSent;
         protected long streamingWritesCounter;  // Number of streaming send operations started so far.
         protected long streamingWritesCounter;  // Number of streaming send operations started so far.
 
 
-        public AsyncCallBase(Func<TWrite, byte[]> serializer, Func<byte[], TRead> deserializer)
+        public AsyncCallBase(Action<TWrite, SerializationContext> serializer, Func<DeserializationContext, TRead> deserializer)
         {
         {
             this.serializer = GrpcPreconditions.CheckNotNull(serializer);
             this.serializer = GrpcPreconditions.CheckNotNull(serializer);
             this.deserializer = GrpcPreconditions.CheckNotNull(deserializer);
             this.deserializer = GrpcPreconditions.CheckNotNull(deserializer);
@@ -215,14 +215,26 @@ namespace Grpc.Core.Internal
 
 
         protected byte[] UnsafeSerialize(TWrite msg)
         protected byte[] UnsafeSerialize(TWrite msg)
         {
         {
-            return serializer(msg);
+            DefaultSerializationContext context = null;
+            try
+            {
+                context = DefaultSerializationContext.GetInitializedThreadLocal();
+                serializer(msg, context);
+                return context.GetPayload();
+            }
+            finally
+            {
+                context?.Reset();
+            }
         }
         }
 
 
         protected Exception TryDeserialize(byte[] payload, out TRead msg)
         protected Exception TryDeserialize(byte[] payload, out TRead msg)
         {
         {
+            DefaultDeserializationContext context = null;
             try
             try
             {
             {
-                msg = deserializer(payload);
+                context = DefaultDeserializationContext.GetInitializedThreadLocal(payload);
+                msg = deserializer(context);
                 return null;
                 return null;
             }
             }
             catch (Exception e)
             catch (Exception e)
@@ -230,6 +242,11 @@ namespace Grpc.Core.Internal
                 msg = default(TRead);
                 msg = default(TRead);
                 return e;
                 return e;
             }
             }
+            finally
+            {
+                context?.Reset();
+
+            }
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 1 - 1
src/csharp/Grpc.Core/Internal/AsyncCallServer.cs

@@ -37,7 +37,7 @@ namespace Grpc.Core.Internal
         readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
         readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
         readonly Server server;
         readonly Server server;
 
 
-        public AsyncCallServer(Func<TResponse, byte[]> serializer, Func<byte[], TRequest> deserializer, Server server) : base(serializer, deserializer)
+        public AsyncCallServer(Action<TResponse, SerializationContext> serializer, Func<DeserializationContext, TRequest> deserializer, Server server) : base(serializer, deserializer)
         {
         {
             this.server = GrpcPreconditions.CheckNotNull(server);
             this.server = GrpcPreconditions.CheckNotNull(server);
         }
         }

+ 66 - 0
src/csharp/Grpc.Core/Internal/DefaultDeserializationContext.cs

@@ -0,0 +1,66 @@
+#region Copyright notice and license
+
+// Copyright 2018 The gRPC Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#endregion
+
+using Grpc.Core.Utils;
+using System;
+using System.Threading;
+
+namespace Grpc.Core.Internal
+{
+    internal class DefaultDeserializationContext : DeserializationContext
+    {
+        static readonly ThreadLocal<DefaultDeserializationContext> threadLocalInstance =
+            new ThreadLocal<DefaultDeserializationContext>(() => new DefaultDeserializationContext(), false);
+
+        byte[] payload;
+        bool alreadyCalledPayloadAsNewBuffer;
+
+        public DefaultDeserializationContext()
+        {
+            Reset();
+        }
+
+        public override int PayloadLength => payload.Length;
+
+        public override byte[] PayloadAsNewBuffer()
+        {
+            GrpcPreconditions.CheckState(!alreadyCalledPayloadAsNewBuffer);
+            alreadyCalledPayloadAsNewBuffer = true;
+            return payload;
+        }
+
+        public void Initialize(byte[] payload)
+        {
+            this.payload = GrpcPreconditions.CheckNotNull(payload);
+            this.alreadyCalledPayloadAsNewBuffer = false;
+        }
+
+        public void Reset()
+        {
+            this.payload = null;
+            this.alreadyCalledPayloadAsNewBuffer = true;  // mark payload as read
+        }
+
+        public static DefaultDeserializationContext GetInitializedThreadLocal(byte[] payload)
+        {
+            var instance = threadLocalInstance.Value;
+            instance.Initialize(payload);
+            return instance;
+        }
+    }
+}

+ 62 - 0
src/csharp/Grpc.Core/Internal/DefaultSerializationContext.cs

@@ -0,0 +1,62 @@
+#region Copyright notice and license
+
+// Copyright 2018 The gRPC Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#endregion
+
+using Grpc.Core.Utils;
+using System.Threading;
+
+namespace Grpc.Core.Internal
+{
+    internal class DefaultSerializationContext : SerializationContext
+    {
+        static readonly ThreadLocal<DefaultSerializationContext> threadLocalInstance =
+            new ThreadLocal<DefaultSerializationContext>(() => new DefaultSerializationContext(), false);
+
+        bool isComplete;
+        byte[] payload;
+
+        public DefaultSerializationContext()
+        {
+            Reset();
+        }
+
+        public override void Complete(byte[] payload)
+        {
+            GrpcPreconditions.CheckState(!isComplete);
+            this.isComplete = true;
+            this.payload = payload;
+        }
+
+        internal byte[] GetPayload()
+        {
+            return this.payload;
+        }
+
+        public void Reset()
+        {
+            this.isComplete = false;
+            this.payload = null;
+        }
+
+        public static DefaultSerializationContext GetInitializedThreadLocal()
+        {
+            var instance = threadLocalInstance.Value;
+            instance.Reset();
+            return instance;
+        }
+    }
+}

+ 8 - 8
src/csharp/Grpc.Core/Internal/ServerCallHandler.cs

@@ -52,8 +52,8 @@ namespace Grpc.Core.Internal
         public async Task HandleCall(ServerRpcNew newRpc, CompletionQueueSafeHandle cq)
         public async Task HandleCall(ServerRpcNew newRpc, CompletionQueueSafeHandle cq)
         {
         {
             var asyncCall = new AsyncCallServer<TRequest, TResponse>(
             var asyncCall = new AsyncCallServer<TRequest, TResponse>(
-                method.ResponseMarshaller.Serializer,
-                method.RequestMarshaller.Deserializer,
+                method.ResponseMarshaller.ContextualSerializer,
+                method.RequestMarshaller.ContextualDeserializer,
                 newRpc.Server);
                 newRpc.Server);
 
 
             asyncCall.Initialize(newRpc.Call, cq);
             asyncCall.Initialize(newRpc.Call, cq);
@@ -116,8 +116,8 @@ namespace Grpc.Core.Internal
         public async Task HandleCall(ServerRpcNew newRpc, CompletionQueueSafeHandle cq)
         public async Task HandleCall(ServerRpcNew newRpc, CompletionQueueSafeHandle cq)
         {
         {
             var asyncCall = new AsyncCallServer<TRequest, TResponse>(
             var asyncCall = new AsyncCallServer<TRequest, TResponse>(
-                method.ResponseMarshaller.Serializer,
-                method.RequestMarshaller.Deserializer,
+                method.ResponseMarshaller.ContextualSerializer,
+                method.RequestMarshaller.ContextualDeserializer,
                 newRpc.Server);
                 newRpc.Server);
 
 
             asyncCall.Initialize(newRpc.Call, cq);
             asyncCall.Initialize(newRpc.Call, cq);
@@ -179,8 +179,8 @@ namespace Grpc.Core.Internal
         public async Task HandleCall(ServerRpcNew newRpc, CompletionQueueSafeHandle cq)
         public async Task HandleCall(ServerRpcNew newRpc, CompletionQueueSafeHandle cq)
         {
         {
             var asyncCall = new AsyncCallServer<TRequest, TResponse>(
             var asyncCall = new AsyncCallServer<TRequest, TResponse>(
-                method.ResponseMarshaller.Serializer,
-                method.RequestMarshaller.Deserializer,
+                method.ResponseMarshaller.ContextualSerializer,
+                method.RequestMarshaller.ContextualDeserializer,
                 newRpc.Server);
                 newRpc.Server);
 
 
             asyncCall.Initialize(newRpc.Call, cq);
             asyncCall.Initialize(newRpc.Call, cq);
@@ -242,8 +242,8 @@ namespace Grpc.Core.Internal
         public async Task HandleCall(ServerRpcNew newRpc, CompletionQueueSafeHandle cq)
         public async Task HandleCall(ServerRpcNew newRpc, CompletionQueueSafeHandle cq)
         {
         {
             var asyncCall = new AsyncCallServer<TRequest, TResponse>(
             var asyncCall = new AsyncCallServer<TRequest, TResponse>(
-                method.ResponseMarshaller.Serializer,
-                method.RequestMarshaller.Deserializer,
+                method.ResponseMarshaller.ContextualSerializer,
+                method.RequestMarshaller.ContextualDeserializer,
                 newRpc.Server);
                 newRpc.Server);
 
 
             asyncCall.Initialize(newRpc.Call, cq);
             asyncCall.Initialize(newRpc.Call, cq);

+ 6 - 61
src/csharp/Grpc.Core/Marshaller.cs

@@ -41,6 +41,8 @@ namespace Grpc.Core
         {
         {
             this.serializer = GrpcPreconditions.CheckNotNull(serializer, nameof(serializer));
             this.serializer = GrpcPreconditions.CheckNotNull(serializer, nameof(serializer));
             this.deserializer = GrpcPreconditions.CheckNotNull(deserializer, nameof(deserializer));
             this.deserializer = GrpcPreconditions.CheckNotNull(deserializer, nameof(deserializer));
+            // contextual serialization/deserialization is emulated to make the marshaller
+            // usable with the grpc library (required for backward compatibility).
             this.contextualSerializer = EmulateContextualSerializer;
             this.contextualSerializer = EmulateContextualSerializer;
             this.contextualDeserializer = EmulateContextualDeserializer;
             this.contextualDeserializer = EmulateContextualDeserializer;
         }
         }
@@ -57,10 +59,10 @@ namespace Grpc.Core
         {
         {
             this.contextualSerializer = GrpcPreconditions.CheckNotNull(serializer, nameof(serializer));
             this.contextualSerializer = GrpcPreconditions.CheckNotNull(serializer, nameof(serializer));
             this.contextualDeserializer = GrpcPreconditions.CheckNotNull(deserializer, nameof(deserializer));
             this.contextualDeserializer = GrpcPreconditions.CheckNotNull(deserializer, nameof(deserializer));
-            // TODO(jtattermusch): once gRPC C# library switches to using contextual (de)serializer,
-            // emulating the simple (de)serializer will become unnecessary.
-            this.serializer = EmulateSimpleSerializer;
-            this.deserializer = EmulateSimpleDeserializer;
+            // gRPC only uses contextual serializer/deserializer internally, so emulating the legacy
+            // (de)serializer is not necessary.
+            this.serializer = (msg) => { throw new NotImplementedException(); };
+            this.deserializer = (payload) => { throw new NotImplementedException(); };
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -85,25 +87,6 @@ namespace Grpc.Core
         /// </summary>
         /// </summary>
         public Func<DeserializationContext, T> ContextualDeserializer => this.contextualDeserializer;
         public Func<DeserializationContext, T> ContextualDeserializer => this.contextualDeserializer;
 
 
-        // for backward compatibility, emulate the simple serializer using the contextual one
-        private byte[] EmulateSimpleSerializer(T msg)
-        {
-            // TODO(jtattermusch): avoid the allocation by passing a thread-local instance
-            // This code will become unnecessary once gRPC C# library switches to using contextual (de)serializer.
-            var context = new EmulatedSerializationContext();
-            this.contextualSerializer(msg, context);
-            return context.GetPayload();
-        }
-
-        // for backward compatibility, emulate the simple deserializer using the contextual one
-        private T EmulateSimpleDeserializer(byte[] payload)
-        {
-            // TODO(jtattermusch): avoid the allocation by passing a thread-local instance
-            // This code will become unnecessary once gRPC C# library switches to using contextual (de)serializer.
-            var context = new EmulatedDeserializationContext(payload);
-            return this.contextualDeserializer(context);
-        }
-
         // for backward compatibility, emulate the contextual serializer using the simple one
         // for backward compatibility, emulate the contextual serializer using the simple one
         private void EmulateContextualSerializer(T message, SerializationContext context)
         private void EmulateContextualSerializer(T message, SerializationContext context)
         {
         {
@@ -116,44 +99,6 @@ namespace Grpc.Core
         {
         {
             return this.deserializer(context.PayloadAsNewBuffer());
             return this.deserializer(context.PayloadAsNewBuffer());
         }
         }
-
-        internal class EmulatedSerializationContext : SerializationContext
-        {
-            bool isComplete;
-            byte[] payload;
-
-            public override void Complete(byte[] payload)
-            {
-                GrpcPreconditions.CheckState(!isComplete);
-                this.isComplete = true;
-                this.payload = payload;
-            }
-
-            internal byte[] GetPayload()
-            {
-                return this.payload;
-            }
-        }
-
-        internal class EmulatedDeserializationContext : DeserializationContext
-        {
-            readonly byte[] payload;
-            bool alreadyCalledPayloadAsNewBuffer;
-
-            public EmulatedDeserializationContext(byte[] payload)
-            {
-                this.payload = GrpcPreconditions.CheckNotNull(payload);
-            }
-
-            public override int PayloadLength => payload.Length;
-
-            public override byte[] PayloadAsNewBuffer()
-            {
-                GrpcPreconditions.CheckState(!alreadyCalledPayloadAsNewBuffer);
-                alreadyCalledPayloadAsNewBuffer = true;
-                return payload;
-            }
-        }
     }
     }
 
 
     /// <summary>
     /// <summary>

+ 6 - 1
src/csharp/Grpc.Core/SerializationContext.cs

@@ -16,6 +16,8 @@
 
 
 #endregion
 #endregion
 
 
+using System;
+
 namespace Grpc.Core
 namespace Grpc.Core
 {
 {
     /// <summary>
     /// <summary>
@@ -29,6 +31,9 @@ namespace Grpc.Core
         /// payload which must not be accessed afterwards.
         /// payload which must not be accessed afterwards.
         /// </summary>
         /// </summary>
         /// <param name="payload">the serialized form of current message</param>
         /// <param name="payload">the serialized form of current message</param>
-        public abstract void Complete(byte[] payload);
+        public virtual void Complete(byte[] payload)
+        {
+            throw new NotImplementedException();
+        }
     }
     }
 }
 }

+ 4 - 4
src/csharp/Grpc.Core/ServerServiceDefinition.cs

@@ -72,7 +72,7 @@ namespace Grpc.Core
             }
             }
 
 
             /// <summary>
             /// <summary>
-            /// Adds a definitions for a single request - single response method.
+            /// Adds a definition for a single request - single response method.
             /// </summary>
             /// </summary>
             /// <typeparam name="TRequest">The request message class.</typeparam>
             /// <typeparam name="TRequest">The request message class.</typeparam>
             /// <typeparam name="TResponse">The response message class.</typeparam>
             /// <typeparam name="TResponse">The response message class.</typeparam>
@@ -90,7 +90,7 @@ namespace Grpc.Core
             }
             }
 
 
             /// <summary>
             /// <summary>
-            /// Adds a definitions for a client streaming method.
+            /// Adds a definition for a client streaming method.
             /// </summary>
             /// </summary>
             /// <typeparam name="TRequest">The request message class.</typeparam>
             /// <typeparam name="TRequest">The request message class.</typeparam>
             /// <typeparam name="TResponse">The response message class.</typeparam>
             /// <typeparam name="TResponse">The response message class.</typeparam>
@@ -108,7 +108,7 @@ namespace Grpc.Core
             }
             }
 
 
             /// <summary>
             /// <summary>
-            /// Adds a definitions for a server streaming method.
+            /// Adds a definition for a server streaming method.
             /// </summary>
             /// </summary>
             /// <typeparam name="TRequest">The request message class.</typeparam>
             /// <typeparam name="TRequest">The request message class.</typeparam>
             /// <typeparam name="TResponse">The response message class.</typeparam>
             /// <typeparam name="TResponse">The response message class.</typeparam>
@@ -126,7 +126,7 @@ namespace Grpc.Core
             }
             }
 
 
             /// <summary>
             /// <summary>
-            /// Adds a definitions for a bidirectional streaming method.
+            /// Adds a definition for a bidirectional streaming method.
             /// </summary>
             /// </summary>
             /// <typeparam name="TRequest">The request message class.</typeparam>
             /// <typeparam name="TRequest">The request message class.</typeparam>
             /// <typeparam name="TResponse">The response message class.</typeparam>
             /// <typeparam name="TResponse">The response message class.</typeparam>

+ 101 - 0
src/csharp/Grpc.Core/ServiceBinderBase.cs

@@ -0,0 +1,101 @@
+#region Copyright notice and license
+
+// Copyright 2018 The gRPC Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using Grpc.Core.Interceptors;
+using Grpc.Core.Internal;
+using Grpc.Core.Utils;
+
+namespace Grpc.Core
+{
+    /// <summary>
+    /// Allows binding server-side method implementations in alternative serving stacks.
+    /// Instances of this class are usually populated by the <c>BindService</c> method
+    /// that is part of the autogenerated code for a protocol buffers service definition.
+    /// <seealso cref="ServerServiceDefinition"/>
+    /// </summary>
+    public class ServiceBinderBase
+    {
+        /// <summary>
+        /// Adds a definition for a single request - single response method.
+        /// </summary>
+        /// <typeparam name="TRequest">The request message class.</typeparam>
+        /// <typeparam name="TResponse">The response message class.</typeparam>
+        /// <param name="method">The method.</param>
+        /// <param name="handler">The method handler.</param>
+        public virtual void AddMethod<TRequest, TResponse>(
+            Method<TRequest, TResponse> method,
+            UnaryServerMethod<TRequest, TResponse> handler)
+                where TRequest : class
+                where TResponse : class
+        {
+            throw new NotImplementedException();
+        }
+
+        /// <summary>
+        /// Adds a definition for a client streaming method.
+        /// </summary>
+        /// <typeparam name="TRequest">The request message class.</typeparam>
+        /// <typeparam name="TResponse">The response message class.</typeparam>
+        /// <param name="method">The method.</param>
+        /// <param name="handler">The method handler.</param>
+        public virtual void AddMethod<TRequest, TResponse>(
+            Method<TRequest, TResponse> method,
+            ClientStreamingServerMethod<TRequest, TResponse> handler)
+                where TRequest : class
+                where TResponse : class
+        {
+            throw new NotImplementedException();
+        }
+
+        /// <summary>
+        /// Adds a definition for a server streaming method.
+        /// </summary>
+        /// <typeparam name="TRequest">The request message class.</typeparam>
+        /// <typeparam name="TResponse">The response message class.</typeparam>
+        /// <param name="method">The method.</param>
+        /// <param name="handler">The method handler.</param>
+        public virtual void AddMethod<TRequest, TResponse>(
+            Method<TRequest, TResponse> method,
+            ServerStreamingServerMethod<TRequest, TResponse> handler)
+                where TRequest : class
+                where TResponse : class
+        {
+            throw new NotImplementedException();
+        }
+
+        /// <summary>
+        /// Adds a definition for a bidirectional streaming method.
+        /// </summary>
+        /// <typeparam name="TRequest">The request message class.</typeparam>
+        /// <typeparam name="TResponse">The response message class.</typeparam>
+        /// <param name="method">The method.</param>
+        /// <param name="handler">The method handler.</param>
+        public virtual void AddMethod<TRequest, TResponse>(
+            Method<TRequest, TResponse> method,
+            DuplexStreamingServerMethod<TRequest, TResponse> handler)
+                where TRequest : class
+                where TResponse : class
+        {
+            throw new NotImplementedException();
+        }
+    }
+}

+ 1 - 1
src/csharp/Grpc.Core/Version.csproj.include

@@ -1,7 +1,7 @@
 <!-- This file is generated -->
 <!-- This file is generated -->
 <Project>
 <Project>
   <PropertyGroup>
   <PropertyGroup>
-    <GrpcCsharpVersion>1.17.0-dev</GrpcCsharpVersion>
+    <GrpcCsharpVersion>1.18.0-dev</GrpcCsharpVersion>
     <GoogleProtobufVersion>3.6.1</GoogleProtobufVersion>
     <GoogleProtobufVersion>3.6.1</GoogleProtobufVersion>
   </PropertyGroup>
   </PropertyGroup>
 </Project>
 </Project>

+ 2 - 2
src/csharp/Grpc.Core/VersionInfo.cs

@@ -33,11 +33,11 @@ namespace Grpc.Core
         /// <summary>
         /// <summary>
         /// Current <c>AssemblyFileVersion</c> of gRPC C# assemblies
         /// Current <c>AssemblyFileVersion</c> of gRPC C# assemblies
         /// </summary>
         /// </summary>
-        public const string CurrentAssemblyFileVersion = "1.17.0.0";
+        public const string CurrentAssemblyFileVersion = "1.18.0.0";
 
 
         /// <summary>
         /// <summary>
         /// Current version of gRPC C#
         /// Current version of gRPC C#
         /// </summary>
         /// </summary>
-        public const string CurrentVersion = "1.17.0-dev";
+        public const string CurrentVersion = "1.18.0-dev";
     }
     }
 }
 }

+ 12 - 0
src/csharp/Grpc.Examples/MathGrpc.cs

@@ -287,6 +287,18 @@ namespace Math {
           .AddMethod(__Method_Sum, serviceImpl.Sum).Build();
           .AddMethod(__Method_Sum, serviceImpl.Sum).Build();
     }
     }
 
 
+    /// <summary>Register service method implementations with a service binder. Useful when customizing the service binding logic.
+    /// Note: this method is part of an experimental API that can change or be removed without any prior notice.</summary>
+    /// <param name="serviceBinder">Service methods will be bound by calling <c>AddMethod</c> on this object.</param>
+    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
+    public static void BindService(grpc::ServiceBinderBase serviceBinder, MathBase serviceImpl)
+    {
+      serviceBinder.AddMethod(__Method_Div, serviceImpl.Div);
+      serviceBinder.AddMethod(__Method_DivMany, serviceImpl.DivMany);
+      serviceBinder.AddMethod(__Method_Fib, serviceImpl.Fib);
+      serviceBinder.AddMethod(__Method_Sum, serviceImpl.Sum);
+    }
+
   }
   }
 }
 }
 #endregion
 #endregion

+ 13 - 7
src/csharp/Grpc.HealthCheck/Health.cs

@@ -25,15 +25,17 @@ namespace Grpc.Health.V1 {
       byte[] descriptorData = global::System.Convert.FromBase64String(
       byte[] descriptorData = global::System.Convert.FromBase64String(
           string.Concat(
           string.Concat(
             "ChtncnBjL2hlYWx0aC92MS9oZWFsdGgucHJvdG8SDmdycGMuaGVhbHRoLnYx",
             "ChtncnBjL2hlYWx0aC92MS9oZWFsdGgucHJvdG8SDmdycGMuaGVhbHRoLnYx",
-            "IiUKEkhlYWx0aENoZWNrUmVxdWVzdBIPCgdzZXJ2aWNlGAEgASgJIpQBChNI",
+            "IiUKEkhlYWx0aENoZWNrUmVxdWVzdBIPCgdzZXJ2aWNlGAEgASgJIqkBChNI",
             "ZWFsdGhDaGVja1Jlc3BvbnNlEkEKBnN0YXR1cxgBIAEoDjIxLmdycGMuaGVh",
             "ZWFsdGhDaGVja1Jlc3BvbnNlEkEKBnN0YXR1cxgBIAEoDjIxLmdycGMuaGVh",
-            "bHRoLnYxLkhlYWx0aENoZWNrUmVzcG9uc2UuU2VydmluZ1N0YXR1cyI6Cg1T",
+            "bHRoLnYxLkhlYWx0aENoZWNrUmVzcG9uc2UuU2VydmluZ1N0YXR1cyJPCg1T",
             "ZXJ2aW5nU3RhdHVzEgsKB1VOS05PV04QABILCgdTRVJWSU5HEAESDwoLTk9U",
             "ZXJ2aW5nU3RhdHVzEgsKB1VOS05PV04QABILCgdTRVJWSU5HEAESDwoLTk9U",
-            "X1NFUlZJTkcQAjJaCgZIZWFsdGgSUAoFQ2hlY2sSIi5ncnBjLmhlYWx0aC52",
-            "MS5IZWFsdGhDaGVja1JlcXVlc3QaIy5ncnBjLmhlYWx0aC52MS5IZWFsdGhD",
-            "aGVja1Jlc3BvbnNlQmEKEWlvLmdycGMuaGVhbHRoLnYxQgtIZWFsdGhQcm90",
-            "b1ABWixnb29nbGUuZ29sYW5nLm9yZy9ncnBjL2hlYWx0aC9ncnBjX2hlYWx0",
-            "aF92MaoCDkdycGMuSGVhbHRoLlYxYgZwcm90bzM="));
+            "X1NFUlZJTkcQAhITCg9TRVJWSUNFX1VOS05PV04QAzKuAQoGSGVhbHRoElAK",
+            "BUNoZWNrEiIuZ3JwYy5oZWFsdGgudjEuSGVhbHRoQ2hlY2tSZXF1ZXN0GiMu",
+            "Z3JwYy5oZWFsdGgudjEuSGVhbHRoQ2hlY2tSZXNwb25zZRJSCgVXYXRjaBIi",
+            "LmdycGMuaGVhbHRoLnYxLkhlYWx0aENoZWNrUmVxdWVzdBojLmdycGMuaGVh",
+            "bHRoLnYxLkhlYWx0aENoZWNrUmVzcG9uc2UwAUJhChFpby5ncnBjLmhlYWx0",
+            "aC52MUILSGVhbHRoUHJvdG9QAVosZ29vZ2xlLmdvbGFuZy5vcmcvZ3JwYy9o",
+            "ZWFsdGgvZ3JwY19oZWFsdGhfdjGqAg5HcnBjLkhlYWx0aC5WMWIGcHJvdG8z"));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { },
           new pbr::FileDescriptor[] { },
           new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
           new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
@@ -309,6 +311,10 @@ namespace Grpc.Health.V1 {
         [pbr::OriginalName("UNKNOWN")] Unknown = 0,
         [pbr::OriginalName("UNKNOWN")] Unknown = 0,
         [pbr::OriginalName("SERVING")] Serving = 1,
         [pbr::OriginalName("SERVING")] Serving = 1,
         [pbr::OriginalName("NOT_SERVING")] NotServing = 2,
         [pbr::OriginalName("NOT_SERVING")] NotServing = 2,
+        /// <summary>
+        /// Used only by the Watch method.
+        /// </summary>
+        [pbr::OriginalName("SERVICE_UNKNOWN")] ServiceUnknown = 3,
       }
       }
 
 
     }
     }

+ 134 - 1
src/csharp/Grpc.HealthCheck/HealthGrpc.cs

@@ -40,6 +40,13 @@ namespace Grpc.Health.V1 {
         __Marshaller_grpc_health_v1_HealthCheckRequest,
         __Marshaller_grpc_health_v1_HealthCheckRequest,
         __Marshaller_grpc_health_v1_HealthCheckResponse);
         __Marshaller_grpc_health_v1_HealthCheckResponse);
 
 
+    static readonly grpc::Method<global::Grpc.Health.V1.HealthCheckRequest, global::Grpc.Health.V1.HealthCheckResponse> __Method_Watch = new grpc::Method<global::Grpc.Health.V1.HealthCheckRequest, global::Grpc.Health.V1.HealthCheckResponse>(
+        grpc::MethodType.ServerStreaming,
+        __ServiceName,
+        "Watch",
+        __Marshaller_grpc_health_v1_HealthCheckRequest,
+        __Marshaller_grpc_health_v1_HealthCheckResponse);
+
     /// <summary>Service descriptor</summary>
     /// <summary>Service descriptor</summary>
     public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
     public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
     {
     {
@@ -49,11 +56,44 @@ namespace Grpc.Health.V1 {
     /// <summary>Base class for server-side implementations of Health</summary>
     /// <summary>Base class for server-side implementations of Health</summary>
     public abstract partial class HealthBase
     public abstract partial class HealthBase
     {
     {
+      /// <summary>
+      /// If the requested service is unknown, the call will fail with status
+      /// NOT_FOUND.
+      /// </summary>
+      /// <param name="request">The request received from the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>The response to send back to the client (wrapped by a task).</returns>
       public virtual global::System.Threading.Tasks.Task<global::Grpc.Health.V1.HealthCheckResponse> Check(global::Grpc.Health.V1.HealthCheckRequest request, grpc::ServerCallContext context)
       public virtual global::System.Threading.Tasks.Task<global::Grpc.Health.V1.HealthCheckResponse> Check(global::Grpc.Health.V1.HealthCheckRequest request, grpc::ServerCallContext context)
       {
       {
         throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
         throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
       }
       }
 
 
+      /// <summary>
+      /// Performs a watch for the serving status of the requested service.
+      /// The server will immediately send back a message indicating the current
+      /// serving status.  It will then subsequently send a new message whenever
+      /// the service's serving status changes.
+      ///
+      /// If the requested service is unknown when the call is received, the
+      /// server will send a message setting the serving status to
+      /// SERVICE_UNKNOWN but will *not* terminate the call.  If at some
+      /// future point, the serving status of the service becomes known, the
+      /// server will send a new message with the service's serving status.
+      ///
+      /// If the call terminates with status UNIMPLEMENTED, then clients
+      /// should assume this method is not supported and should not retry the
+      /// call.  If the call terminates with any other status (including OK),
+      /// clients should retry the call with appropriate exponential backoff.
+      /// </summary>
+      /// <param name="request">The request received from the client.</param>
+      /// <param name="responseStream">Used for sending responses back to the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>A task indicating completion of the handler.</returns>
+      public virtual global::System.Threading.Tasks.Task Watch(global::Grpc.Health.V1.HealthCheckRequest request, grpc::IServerStreamWriter<global::Grpc.Health.V1.HealthCheckResponse> responseStream, grpc::ServerCallContext context)
+      {
+        throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
+      }
+
     }
     }
 
 
     /// <summary>Client for Health</summary>
     /// <summary>Client for Health</summary>
@@ -79,22 +119,104 @@ namespace Grpc.Health.V1 {
       {
       {
       }
       }
 
 
+      /// <summary>
+      /// If the requested service is unknown, the call will fail with status
+      /// NOT_FOUND.
+      /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The response received from the server.</returns>
       public virtual global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
       public virtual global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
       {
       {
         return Check(request, new grpc::CallOptions(headers, deadline, cancellationToken));
         return Check(request, new grpc::CallOptions(headers, deadline, cancellationToken));
       }
       }
+      /// <summary>
+      /// If the requested service is unknown, the call will fail with status
+      /// NOT_FOUND.
+      /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The response received from the server.</returns>
       public virtual global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, grpc::CallOptions options)
       public virtual global::Grpc.Health.V1.HealthCheckResponse Check(global::Grpc.Health.V1.HealthCheckRequest request, grpc::CallOptions options)
       {
       {
         return CallInvoker.BlockingUnaryCall(__Method_Check, null, options, request);
         return CallInvoker.BlockingUnaryCall(__Method_Check, null, options, request);
       }
       }
+      /// <summary>
+      /// If the requested service is unknown, the call will fail with status
+      /// NOT_FOUND.
+      /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
       public virtual grpc::AsyncUnaryCall<global::Grpc.Health.V1.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1.HealthCheckRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
       public virtual grpc::AsyncUnaryCall<global::Grpc.Health.V1.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1.HealthCheckRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
       {
       {
         return CheckAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
         return CheckAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
       }
       }
+      /// <summary>
+      /// If the requested service is unknown, the call will fail with status
+      /// NOT_FOUND.
+      /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
       public virtual grpc::AsyncUnaryCall<global::Grpc.Health.V1.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1.HealthCheckRequest request, grpc::CallOptions options)
       public virtual grpc::AsyncUnaryCall<global::Grpc.Health.V1.HealthCheckResponse> CheckAsync(global::Grpc.Health.V1.HealthCheckRequest request, grpc::CallOptions options)
       {
       {
         return CallInvoker.AsyncUnaryCall(__Method_Check, null, options, request);
         return CallInvoker.AsyncUnaryCall(__Method_Check, null, options, request);
       }
       }
+      /// <summary>
+      /// Performs a watch for the serving status of the requested service.
+      /// The server will immediately send back a message indicating the current
+      /// serving status.  It will then subsequently send a new message whenever
+      /// the service's serving status changes.
+      ///
+      /// If the requested service is unknown when the call is received, the
+      /// server will send a message setting the serving status to
+      /// SERVICE_UNKNOWN but will *not* terminate the call.  If at some
+      /// future point, the serving status of the service becomes known, the
+      /// server will send a new message with the service's serving status.
+      ///
+      /// If the call terminates with status UNIMPLEMENTED, then clients
+      /// should assume this method is not supported and should not retry the
+      /// call.  If the call terminates with any other status (including OK),
+      /// clients should retry the call with appropriate exponential backoff.
+      /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
+      public virtual grpc::AsyncServerStreamingCall<global::Grpc.Health.V1.HealthCheckResponse> Watch(global::Grpc.Health.V1.HealthCheckRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
+      {
+        return Watch(request, new grpc::CallOptions(headers, deadline, cancellationToken));
+      }
+      /// <summary>
+      /// Performs a watch for the serving status of the requested service.
+      /// The server will immediately send back a message indicating the current
+      /// serving status.  It will then subsequently send a new message whenever
+      /// the service's serving status changes.
+      ///
+      /// If the requested service is unknown when the call is received, the
+      /// server will send a message setting the serving status to
+      /// SERVICE_UNKNOWN but will *not* terminate the call.  If at some
+      /// future point, the serving status of the service becomes known, the
+      /// server will send a new message with the service's serving status.
+      ///
+      /// If the call terminates with status UNIMPLEMENTED, then clients
+      /// should assume this method is not supported and should not retry the
+      /// call.  If the call terminates with any other status (including OK),
+      /// clients should retry the call with appropriate exponential backoff.
+      /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
+      public virtual grpc::AsyncServerStreamingCall<global::Grpc.Health.V1.HealthCheckResponse> Watch(global::Grpc.Health.V1.HealthCheckRequest request, grpc::CallOptions options)
+      {
+        return CallInvoker.AsyncServerStreamingCall(__Method_Watch, null, options, request);
+      }
       /// <summary>Creates a new instance of client from given <c>ClientBaseConfiguration</c>.</summary>
       /// <summary>Creates a new instance of client from given <c>ClientBaseConfiguration</c>.</summary>
       protected override HealthClient NewInstance(ClientBaseConfiguration configuration)
       protected override HealthClient NewInstance(ClientBaseConfiguration configuration)
       {
       {
@@ -107,7 +229,18 @@ namespace Grpc.Health.V1 {
     public static grpc::ServerServiceDefinition BindService(HealthBase serviceImpl)
     public static grpc::ServerServiceDefinition BindService(HealthBase serviceImpl)
     {
     {
       return grpc::ServerServiceDefinition.CreateBuilder()
       return grpc::ServerServiceDefinition.CreateBuilder()
-          .AddMethod(__Method_Check, serviceImpl.Check).Build();
+          .AddMethod(__Method_Check, serviceImpl.Check)
+          .AddMethod(__Method_Watch, serviceImpl.Watch).Build();
+    }
+
+    /// <summary>Register service method implementations with a service binder. Useful when customizing the service binding logic.
+    /// Note: this method is part of an experimental API that can change or be removed without any prior notice.</summary>
+    /// <param name="serviceBinder">Service methods will be bound by calling <c>AddMethod</c> on this object.</param>
+    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
+    public static void BindService(grpc::ServiceBinderBase serviceBinder, HealthBase serviceImpl)
+    {
+      serviceBinder.AddMethod(__Method_Check, serviceImpl.Check);
+      serviceBinder.AddMethod(__Method_Watch, serviceImpl.Watch);
     }
     }
 
 
   }
   }

+ 13 - 0
src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs

@@ -324,6 +324,19 @@ namespace Grpc.Testing {
           .AddMethod(__Method_StreamingBothWays, serviceImpl.StreamingBothWays).Build();
           .AddMethod(__Method_StreamingBothWays, serviceImpl.StreamingBothWays).Build();
     }
     }
 
 
+    /// <summary>Register service method implementations with a service binder. Useful when customizing the service binding logic.
+    /// Note: this method is part of an experimental API that can change or be removed without any prior notice.</summary>
+    /// <param name="serviceBinder">Service methods will be bound by calling <c>AddMethod</c> on this object.</param>
+    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
+    public static void BindService(grpc::ServiceBinderBase serviceBinder, BenchmarkServiceBase serviceImpl)
+    {
+      serviceBinder.AddMethod(__Method_UnaryCall, serviceImpl.UnaryCall);
+      serviceBinder.AddMethod(__Method_StreamingCall, serviceImpl.StreamingCall);
+      serviceBinder.AddMethod(__Method_StreamingFromClient, serviceImpl.StreamingFromClient);
+      serviceBinder.AddMethod(__Method_StreamingFromServer, serviceImpl.StreamingFromServer);
+      serviceBinder.AddMethod(__Method_StreamingBothWays, serviceImpl.StreamingBothWays);
+    }
+
   }
   }
 }
 }
 #endregion
 #endregion

+ 89 - 55
src/csharp/Grpc.IntegrationTesting/Control.cs

@@ -34,7 +34,7 @@ namespace Grpc.Testing {
             "U2VjdXJpdHlQYXJhbXMSEwoLdXNlX3Rlc3RfY2EYASABKAgSHAoUc2VydmVy",
             "U2VjdXJpdHlQYXJhbXMSEwoLdXNlX3Rlc3RfY2EYASABKAgSHAoUc2VydmVy",
             "X2hvc3Rfb3ZlcnJpZGUYAiABKAkSEQoJY3JlZF90eXBlGAMgASgJIk0KCkNo",
             "X2hvc3Rfb3ZlcnJpZGUYAiABKAkSEQoJY3JlZF90eXBlGAMgASgJIk0KCkNo",
             "YW5uZWxBcmcSDAoEbmFtZRgBIAEoCRITCglzdHJfdmFsdWUYAiABKAlIABIT",
             "YW5uZWxBcmcSDAoEbmFtZRgBIAEoCRITCglzdHJfdmFsdWUYAiABKAlIABIT",
-            "CglpbnRfdmFsdWUYAyABKAVIAEIHCgV2YWx1ZSLvBAoMQ2xpZW50Q29uZmln",
+            "CglpbnRfdmFsdWUYAyABKAVIAEIHCgV2YWx1ZSKiBQoMQ2xpZW50Q29uZmln",
             "EhYKDnNlcnZlcl90YXJnZXRzGAEgAygJEi0KC2NsaWVudF90eXBlGAIgASgO",
             "EhYKDnNlcnZlcl90YXJnZXRzGAEgAygJEi0KC2NsaWVudF90eXBlGAIgASgO",
             "MhguZ3JwYy50ZXN0aW5nLkNsaWVudFR5cGUSNQoPc2VjdXJpdHlfcGFyYW1z",
             "MhguZ3JwYy50ZXN0aW5nLkNsaWVudFR5cGUSNQoPc2VjdXJpdHlfcGFyYW1z",
             "GAMgASgLMhwuZ3JwYy50ZXN0aW5nLlNlY3VyaXR5UGFyYW1zEiQKHG91dHN0",
             "GAMgASgLMhwuZ3JwYy50ZXN0aW5nLlNlY3VyaXR5UGFyYW1zEiQKHG91dHN0",
@@ -48,59 +48,60 @@ namespace Grpc.Testing {
             "GA4gASgFEhgKEG90aGVyX2NsaWVudF9hcGkYDyABKAkSLgoMY2hhbm5lbF9h",
             "GA4gASgFEhgKEG90aGVyX2NsaWVudF9hcGkYDyABKAkSLgoMY2hhbm5lbF9h",
             "cmdzGBAgAygLMhguZ3JwYy50ZXN0aW5nLkNoYW5uZWxBcmcSFgoOdGhyZWFk",
             "cmdzGBAgAygLMhguZ3JwYy50ZXN0aW5nLkNoYW5uZWxBcmcSFgoOdGhyZWFk",
             "c19wZXJfY3EYESABKAUSGwoTbWVzc2FnZXNfcGVyX3N0cmVhbRgSIAEoBRIY",
             "c19wZXJfY3EYESABKAUSGwoTbWVzc2FnZXNfcGVyX3N0cmVhbRgSIAEoBRIY",
-            "ChB1c2VfY29hbGVzY2VfYXBpGBMgASgIIjgKDENsaWVudFN0YXR1cxIoCgVz",
-            "dGF0cxgBIAEoCzIZLmdycGMudGVzdGluZy5DbGllbnRTdGF0cyIVCgRNYXJr",
-            "Eg0KBXJlc2V0GAEgASgIImgKCkNsaWVudEFyZ3MSKwoFc2V0dXAYASABKAsy",
-            "Gi5ncnBjLnRlc3RpbmcuQ2xpZW50Q29uZmlnSAASIgoEbWFyaxgCIAEoCzIS",
-            "LmdycGMudGVzdGluZy5NYXJrSABCCQoHYXJndHlwZSL9AgoMU2VydmVyQ29u",
-            "ZmlnEi0KC3NlcnZlcl90eXBlGAEgASgOMhguZ3JwYy50ZXN0aW5nLlNlcnZl",
-            "clR5cGUSNQoPc2VjdXJpdHlfcGFyYW1zGAIgASgLMhwuZ3JwYy50ZXN0aW5n",
-            "LlNlY3VyaXR5UGFyYW1zEgwKBHBvcnQYBCABKAUSHAoUYXN5bmNfc2VydmVy",
-            "X3RocmVhZHMYByABKAUSEgoKY29yZV9saW1pdBgIIAEoBRIzCg5wYXlsb2Fk",
-            "X2NvbmZpZxgJIAEoCzIbLmdycGMudGVzdGluZy5QYXlsb2FkQ29uZmlnEhEK",
-            "CWNvcmVfbGlzdBgKIAMoBRIYChBvdGhlcl9zZXJ2ZXJfYXBpGAsgASgJEhYK",
-            "DnRocmVhZHNfcGVyX2NxGAwgASgFEhwKE3Jlc291cmNlX3F1b3RhX3NpemUY",
-            "6QcgASgFEi8KDGNoYW5uZWxfYXJncxjqByADKAsyGC5ncnBjLnRlc3Rpbmcu",
-            "Q2hhbm5lbEFyZyJoCgpTZXJ2ZXJBcmdzEisKBXNldHVwGAEgASgLMhouZ3Jw",
-            "Yy50ZXN0aW5nLlNlcnZlckNvbmZpZ0gAEiIKBG1hcmsYAiABKAsyEi5ncnBj",
-            "LnRlc3RpbmcuTWFya0gAQgkKB2FyZ3R5cGUiVQoMU2VydmVyU3RhdHVzEigK",
-            "BXN0YXRzGAEgASgLMhkuZ3JwYy50ZXN0aW5nLlNlcnZlclN0YXRzEgwKBHBv",
-            "cnQYAiABKAUSDQoFY29yZXMYAyABKAUiDQoLQ29yZVJlcXVlc3QiHQoMQ29y",
-            "ZVJlc3BvbnNlEg0KBWNvcmVzGAEgASgFIgYKBFZvaWQi/QEKCFNjZW5hcmlv",
-            "EgwKBG5hbWUYASABKAkSMQoNY2xpZW50X2NvbmZpZxgCIAEoCzIaLmdycGMu",
-            "dGVzdGluZy5DbGllbnRDb25maWcSEwoLbnVtX2NsaWVudHMYAyABKAUSMQoN",
-            "c2VydmVyX2NvbmZpZxgEIAEoCzIaLmdycGMudGVzdGluZy5TZXJ2ZXJDb25m",
-            "aWcSEwoLbnVtX3NlcnZlcnMYBSABKAUSFgoOd2FybXVwX3NlY29uZHMYBiAB",
-            "KAUSGQoRYmVuY2htYXJrX3NlY29uZHMYByABKAUSIAoYc3Bhd25fbG9jYWxf",
-            "d29ya2VyX2NvdW50GAggASgFIjYKCVNjZW5hcmlvcxIpCglzY2VuYXJpb3MY",
-            "ASADKAsyFi5ncnBjLnRlc3RpbmcuU2NlbmFyaW8ihAQKFVNjZW5hcmlvUmVz",
-            "dWx0U3VtbWFyeRILCgNxcHMYASABKAESGwoTcXBzX3Blcl9zZXJ2ZXJfY29y",
-            "ZRgCIAEoARIaChJzZXJ2ZXJfc3lzdGVtX3RpbWUYAyABKAESGAoQc2VydmVy",
-            "X3VzZXJfdGltZRgEIAEoARIaChJjbGllbnRfc3lzdGVtX3RpbWUYBSABKAES",
-            "GAoQY2xpZW50X3VzZXJfdGltZRgGIAEoARISCgpsYXRlbmN5XzUwGAcgASgB",
-            "EhIKCmxhdGVuY3lfOTAYCCABKAESEgoKbGF0ZW5jeV85NRgJIAEoARISCgps",
-            "YXRlbmN5Xzk5GAogASgBEhMKC2xhdGVuY3lfOTk5GAsgASgBEhgKEHNlcnZl",
-            "cl9jcHVfdXNhZ2UYDCABKAESJgoec3VjY2Vzc2Z1bF9yZXF1ZXN0c19wZXJf",
-            "c2Vjb25kGA0gASgBEiIKGmZhaWxlZF9yZXF1ZXN0c19wZXJfc2Vjb25kGA4g",
-            "ASgBEiAKGGNsaWVudF9wb2xsc19wZXJfcmVxdWVzdBgPIAEoARIgChhzZXJ2",
-            "ZXJfcG9sbHNfcGVyX3JlcXVlc3QYECABKAESIgoac2VydmVyX3F1ZXJpZXNf",
-            "cGVyX2NwdV9zZWMYESABKAESIgoaY2xpZW50X3F1ZXJpZXNfcGVyX2NwdV9z",
-            "ZWMYEiABKAEigwMKDlNjZW5hcmlvUmVzdWx0EigKCHNjZW5hcmlvGAEgASgL",
-            "MhYuZ3JwYy50ZXN0aW5nLlNjZW5hcmlvEi4KCWxhdGVuY2llcxgCIAEoCzIb",
-            "LmdycGMudGVzdGluZy5IaXN0b2dyYW1EYXRhEi8KDGNsaWVudF9zdGF0cxgD",
-            "IAMoCzIZLmdycGMudGVzdGluZy5DbGllbnRTdGF0cxIvCgxzZXJ2ZXJfc3Rh",
-            "dHMYBCADKAsyGS5ncnBjLnRlc3RpbmcuU2VydmVyU3RhdHMSFAoMc2VydmVy",
-            "X2NvcmVzGAUgAygFEjQKB3N1bW1hcnkYBiABKAsyIy5ncnBjLnRlc3Rpbmcu",
-            "U2NlbmFyaW9SZXN1bHRTdW1tYXJ5EhYKDmNsaWVudF9zdWNjZXNzGAcgAygI",
-            "EhYKDnNlcnZlcl9zdWNjZXNzGAggAygIEjkKD3JlcXVlc3RfcmVzdWx0cxgJ",
-            "IAMoCzIgLmdycGMudGVzdGluZy5SZXF1ZXN0UmVzdWx0Q291bnQqQQoKQ2xp",
-            "ZW50VHlwZRIPCgtTWU5DX0NMSUVOVBAAEhAKDEFTWU5DX0NMSUVOVBABEhAK",
-            "DE9USEVSX0NMSUVOVBACKlsKClNlcnZlclR5cGUSDwoLU1lOQ19TRVJWRVIQ",
-            "ABIQCgxBU1lOQ19TRVJWRVIQARIYChRBU1lOQ19HRU5FUklDX1NFUlZFUhAC",
-            "EhAKDE9USEVSX1NFUlZFUhADKnIKB1JwY1R5cGUSCQoFVU5BUlkQABINCglT",
-            "VFJFQU1JTkcQARIZChVTVFJFQU1JTkdfRlJPTV9DTElFTlQQAhIZChVTVFJF",
-            "QU1JTkdfRlJPTV9TRVJWRVIQAxIXChNTVFJFQU1JTkdfQk9USF9XQVlTEARi",
-            "BnByb3RvMw=="));
+            "ChB1c2VfY29hbGVzY2VfYXBpGBMgASgIEjEKKW1lZGlhbl9sYXRlbmN5X2Nv",
+            "bGxlY3Rpb25faW50ZXJ2YWxfbWlsbGlzGBQgASgFIjgKDENsaWVudFN0YXR1",
+            "cxIoCgVzdGF0cxgBIAEoCzIZLmdycGMudGVzdGluZy5DbGllbnRTdGF0cyIV",
+            "CgRNYXJrEg0KBXJlc2V0GAEgASgIImgKCkNsaWVudEFyZ3MSKwoFc2V0dXAY",
+            "ASABKAsyGi5ncnBjLnRlc3RpbmcuQ2xpZW50Q29uZmlnSAASIgoEbWFyaxgC",
+            "IAEoCzISLmdycGMudGVzdGluZy5NYXJrSABCCQoHYXJndHlwZSL9AgoMU2Vy",
+            "dmVyQ29uZmlnEi0KC3NlcnZlcl90eXBlGAEgASgOMhguZ3JwYy50ZXN0aW5n",
+            "LlNlcnZlclR5cGUSNQoPc2VjdXJpdHlfcGFyYW1zGAIgASgLMhwuZ3JwYy50",
+            "ZXN0aW5nLlNlY3VyaXR5UGFyYW1zEgwKBHBvcnQYBCABKAUSHAoUYXN5bmNf",
+            "c2VydmVyX3RocmVhZHMYByABKAUSEgoKY29yZV9saW1pdBgIIAEoBRIzCg5w",
+            "YXlsb2FkX2NvbmZpZxgJIAEoCzIbLmdycGMudGVzdGluZy5QYXlsb2FkQ29u",
+            "ZmlnEhEKCWNvcmVfbGlzdBgKIAMoBRIYChBvdGhlcl9zZXJ2ZXJfYXBpGAsg",
+            "ASgJEhYKDnRocmVhZHNfcGVyX2NxGAwgASgFEhwKE3Jlc291cmNlX3F1b3Rh",
+            "X3NpemUY6QcgASgFEi8KDGNoYW5uZWxfYXJncxjqByADKAsyGC5ncnBjLnRl",
+            "c3RpbmcuQ2hhbm5lbEFyZyJoCgpTZXJ2ZXJBcmdzEisKBXNldHVwGAEgASgL",
+            "MhouZ3JwYy50ZXN0aW5nLlNlcnZlckNvbmZpZ0gAEiIKBG1hcmsYAiABKAsy",
+            "Ei5ncnBjLnRlc3RpbmcuTWFya0gAQgkKB2FyZ3R5cGUiVQoMU2VydmVyU3Rh",
+            "dHVzEigKBXN0YXRzGAEgASgLMhkuZ3JwYy50ZXN0aW5nLlNlcnZlclN0YXRz",
+            "EgwKBHBvcnQYAiABKAUSDQoFY29yZXMYAyABKAUiDQoLQ29yZVJlcXVlc3Qi",
+            "HQoMQ29yZVJlc3BvbnNlEg0KBWNvcmVzGAEgASgFIgYKBFZvaWQi/QEKCFNj",
+            "ZW5hcmlvEgwKBG5hbWUYASABKAkSMQoNY2xpZW50X2NvbmZpZxgCIAEoCzIa",
+            "LmdycGMudGVzdGluZy5DbGllbnRDb25maWcSEwoLbnVtX2NsaWVudHMYAyAB",
+            "KAUSMQoNc2VydmVyX2NvbmZpZxgEIAEoCzIaLmdycGMudGVzdGluZy5TZXJ2",
+            "ZXJDb25maWcSEwoLbnVtX3NlcnZlcnMYBSABKAUSFgoOd2FybXVwX3NlY29u",
+            "ZHMYBiABKAUSGQoRYmVuY2htYXJrX3NlY29uZHMYByABKAUSIAoYc3Bhd25f",
+            "bG9jYWxfd29ya2VyX2NvdW50GAggASgFIjYKCVNjZW5hcmlvcxIpCglzY2Vu",
+            "YXJpb3MYASADKAsyFi5ncnBjLnRlc3RpbmcuU2NlbmFyaW8ihAQKFVNjZW5h",
+            "cmlvUmVzdWx0U3VtbWFyeRILCgNxcHMYASABKAESGwoTcXBzX3Blcl9zZXJ2",
+            "ZXJfY29yZRgCIAEoARIaChJzZXJ2ZXJfc3lzdGVtX3RpbWUYAyABKAESGAoQ",
+            "c2VydmVyX3VzZXJfdGltZRgEIAEoARIaChJjbGllbnRfc3lzdGVtX3RpbWUY",
+            "BSABKAESGAoQY2xpZW50X3VzZXJfdGltZRgGIAEoARISCgpsYXRlbmN5XzUw",
+            "GAcgASgBEhIKCmxhdGVuY3lfOTAYCCABKAESEgoKbGF0ZW5jeV85NRgJIAEo",
+            "ARISCgpsYXRlbmN5Xzk5GAogASgBEhMKC2xhdGVuY3lfOTk5GAsgASgBEhgK",
+            "EHNlcnZlcl9jcHVfdXNhZ2UYDCABKAESJgoec3VjY2Vzc2Z1bF9yZXF1ZXN0",
+            "c19wZXJfc2Vjb25kGA0gASgBEiIKGmZhaWxlZF9yZXF1ZXN0c19wZXJfc2Vj",
+            "b25kGA4gASgBEiAKGGNsaWVudF9wb2xsc19wZXJfcmVxdWVzdBgPIAEoARIg",
+            "ChhzZXJ2ZXJfcG9sbHNfcGVyX3JlcXVlc3QYECABKAESIgoac2VydmVyX3F1",
+            "ZXJpZXNfcGVyX2NwdV9zZWMYESABKAESIgoaY2xpZW50X3F1ZXJpZXNfcGVy",
+            "X2NwdV9zZWMYEiABKAEigwMKDlNjZW5hcmlvUmVzdWx0EigKCHNjZW5hcmlv",
+            "GAEgASgLMhYuZ3JwYy50ZXN0aW5nLlNjZW5hcmlvEi4KCWxhdGVuY2llcxgC",
+            "IAEoCzIbLmdycGMudGVzdGluZy5IaXN0b2dyYW1EYXRhEi8KDGNsaWVudF9z",
+            "dGF0cxgDIAMoCzIZLmdycGMudGVzdGluZy5DbGllbnRTdGF0cxIvCgxzZXJ2",
+            "ZXJfc3RhdHMYBCADKAsyGS5ncnBjLnRlc3RpbmcuU2VydmVyU3RhdHMSFAoM",
+            "c2VydmVyX2NvcmVzGAUgAygFEjQKB3N1bW1hcnkYBiABKAsyIy5ncnBjLnRl",
+            "c3RpbmcuU2NlbmFyaW9SZXN1bHRTdW1tYXJ5EhYKDmNsaWVudF9zdWNjZXNz",
+            "GAcgAygIEhYKDnNlcnZlcl9zdWNjZXNzGAggAygIEjkKD3JlcXVlc3RfcmVz",
+            "dWx0cxgJIAMoCzIgLmdycGMudGVzdGluZy5SZXF1ZXN0UmVzdWx0Q291bnQq",
+            "VgoKQ2xpZW50VHlwZRIPCgtTWU5DX0NMSUVOVBAAEhAKDEFTWU5DX0NMSUVO",
+            "VBABEhAKDE9USEVSX0NMSUVOVBACEhMKD0NBTExCQUNLX0NMSUVOVBADKlsK",
+            "ClNlcnZlclR5cGUSDwoLU1lOQ19TRVJWRVIQABIQCgxBU1lOQ19TRVJWRVIQ",
+            "ARIYChRBU1lOQ19HRU5FUklDX1NFUlZFUhACEhAKDE9USEVSX1NFUlZFUhAD",
+            "KnIKB1JwY1R5cGUSCQoFVU5BUlkQABINCglTVFJFQU1JTkcQARIZChVTVFJF",
+            "QU1JTkdfRlJPTV9DTElFTlQQAhIZChVTVFJFQU1JTkdfRlJPTV9TRVJWRVIQ",
+            "AxIXChNTVFJFQU1JTkdfQk9USF9XQVlTEARiBnByb3RvMw=="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { global::Grpc.Testing.PayloadsReflection.Descriptor, global::Grpc.Testing.StatsReflection.Descriptor, },
           new pbr::FileDescriptor[] { global::Grpc.Testing.PayloadsReflection.Descriptor, global::Grpc.Testing.StatsReflection.Descriptor, },
           new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Grpc.Testing.ClientType), typeof(global::Grpc.Testing.ServerType), typeof(global::Grpc.Testing.RpcType), }, new pbr::GeneratedClrTypeInfo[] {
           new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Grpc.Testing.ClientType), typeof(global::Grpc.Testing.ServerType), typeof(global::Grpc.Testing.RpcType), }, new pbr::GeneratedClrTypeInfo[] {
@@ -109,7 +110,7 @@ namespace Grpc.Testing {
             new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.LoadParams), global::Grpc.Testing.LoadParams.Parser, new[]{ "ClosedLoop", "Poisson" }, new[]{ "Load" }, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.LoadParams), global::Grpc.Testing.LoadParams.Parser, new[]{ "ClosedLoop", "Poisson" }, new[]{ "Load" }, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.SecurityParams), global::Grpc.Testing.SecurityParams.Parser, new[]{ "UseTestCa", "ServerHostOverride", "CredType" }, null, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.SecurityParams), global::Grpc.Testing.SecurityParams.Parser, new[]{ "UseTestCa", "ServerHostOverride", "CredType" }, null, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ChannelArg), global::Grpc.Testing.ChannelArg.Parser, new[]{ "Name", "StrValue", "IntValue" }, new[]{ "Value" }, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ChannelArg), global::Grpc.Testing.ChannelArg.Parser, new[]{ "Name", "StrValue", "IntValue" }, new[]{ "Value" }, null, null),
-            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientConfig), global::Grpc.Testing.ClientConfig.Parser, new[]{ "ServerTargets", "ClientType", "SecurityParams", "OutstandingRpcsPerChannel", "ClientChannels", "AsyncClientThreads", "RpcType", "LoadParams", "PayloadConfig", "HistogramParams", "CoreList", "CoreLimit", "OtherClientApi", "ChannelArgs", "ThreadsPerCq", "MessagesPerStream", "UseCoalesceApi" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientConfig), global::Grpc.Testing.ClientConfig.Parser, new[]{ "ServerTargets", "ClientType", "SecurityParams", "OutstandingRpcsPerChannel", "ClientChannels", "AsyncClientThreads", "RpcType", "LoadParams", "PayloadConfig", "HistogramParams", "CoreList", "CoreLimit", "OtherClientApi", "ChannelArgs", "ThreadsPerCq", "MessagesPerStream", "UseCoalesceApi", "MedianLatencyCollectionIntervalMillis" }, null, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientStatus), global::Grpc.Testing.ClientStatus.Parser, new[]{ "Stats" }, null, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientStatus), global::Grpc.Testing.ClientStatus.Parser, new[]{ "Stats" }, null, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Mark), global::Grpc.Testing.Mark.Parser, new[]{ "Reset" }, null, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.Mark), global::Grpc.Testing.Mark.Parser, new[]{ "Reset" }, null, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientArgs), global::Grpc.Testing.ClientArgs.Parser, new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Grpc.Testing.ClientArgs), global::Grpc.Testing.ClientArgs.Parser, new[]{ "Setup", "Mark" }, new[]{ "Argtype" }, null, null),
@@ -140,6 +141,7 @@ namespace Grpc.Testing {
     /// used for some language-specific variants
     /// used for some language-specific variants
     /// </summary>
     /// </summary>
     [pbr::OriginalName("OTHER_CLIENT")] OtherClient = 2,
     [pbr::OriginalName("OTHER_CLIENT")] OtherClient = 2,
+    [pbr::OriginalName("CALLBACK_CLIENT")] CallbackClient = 3,
   }
   }
 
 
   public enum ServerType {
   public enum ServerType {
@@ -1054,6 +1056,7 @@ namespace Grpc.Testing {
       threadsPerCq_ = other.threadsPerCq_;
       threadsPerCq_ = other.threadsPerCq_;
       messagesPerStream_ = other.messagesPerStream_;
       messagesPerStream_ = other.messagesPerStream_;
       useCoalesceApi_ = other.useCoalesceApi_;
       useCoalesceApi_ = other.useCoalesceApi_;
+      medianLatencyCollectionIntervalMillis_ = other.medianLatencyCollectionIntervalMillis_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
     }
 
 
@@ -1278,6 +1281,21 @@ namespace Grpc.Testing {
       }
       }
     }
     }
 
 
+    /// <summary>Field number for the "median_latency_collection_interval_millis" field.</summary>
+    public const int MedianLatencyCollectionIntervalMillisFieldNumber = 20;
+    private int medianLatencyCollectionIntervalMillis_;
+    /// <summary>
+    /// If 0, disabled. Else, specifies the period between gathering latency
+    /// medians in milliseconds.
+    /// </summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    public int MedianLatencyCollectionIntervalMillis {
+      get { return medianLatencyCollectionIntervalMillis_; }
+      set {
+        medianLatencyCollectionIntervalMillis_ = value;
+      }
+    }
+
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override bool Equals(object other) {
     public override bool Equals(object other) {
       return Equals(other as ClientConfig);
       return Equals(other as ClientConfig);
@@ -1308,6 +1326,7 @@ namespace Grpc.Testing {
       if (ThreadsPerCq != other.ThreadsPerCq) return false;
       if (ThreadsPerCq != other.ThreadsPerCq) return false;
       if (MessagesPerStream != other.MessagesPerStream) return false;
       if (MessagesPerStream != other.MessagesPerStream) return false;
       if (UseCoalesceApi != other.UseCoalesceApi) return false;
       if (UseCoalesceApi != other.UseCoalesceApi) return false;
+      if (MedianLatencyCollectionIntervalMillis != other.MedianLatencyCollectionIntervalMillis) return false;
       return Equals(_unknownFields, other._unknownFields);
       return Equals(_unknownFields, other._unknownFields);
     }
     }
 
 
@@ -1331,6 +1350,7 @@ namespace Grpc.Testing {
       if (ThreadsPerCq != 0) hash ^= ThreadsPerCq.GetHashCode();
       if (ThreadsPerCq != 0) hash ^= ThreadsPerCq.GetHashCode();
       if (MessagesPerStream != 0) hash ^= MessagesPerStream.GetHashCode();
       if (MessagesPerStream != 0) hash ^= MessagesPerStream.GetHashCode();
       if (UseCoalesceApi != false) hash ^= UseCoalesceApi.GetHashCode();
       if (UseCoalesceApi != false) hash ^= UseCoalesceApi.GetHashCode();
+      if (MedianLatencyCollectionIntervalMillis != 0) hash ^= MedianLatencyCollectionIntervalMillis.GetHashCode();
       if (_unknownFields != null) {
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
         hash ^= _unknownFields.GetHashCode();
       }
       }
@@ -1403,6 +1423,10 @@ namespace Grpc.Testing {
         output.WriteRawTag(152, 1);
         output.WriteRawTag(152, 1);
         output.WriteBool(UseCoalesceApi);
         output.WriteBool(UseCoalesceApi);
       }
       }
+      if (MedianLatencyCollectionIntervalMillis != 0) {
+        output.WriteRawTag(160, 1);
+        output.WriteInt32(MedianLatencyCollectionIntervalMillis);
+      }
       if (_unknownFields != null) {
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
         _unknownFields.WriteTo(output);
       }
       }
@@ -1456,6 +1480,9 @@ namespace Grpc.Testing {
       if (UseCoalesceApi != false) {
       if (UseCoalesceApi != false) {
         size += 2 + 1;
         size += 2 + 1;
       }
       }
+      if (MedianLatencyCollectionIntervalMillis != 0) {
+        size += 2 + pb::CodedOutputStream.ComputeInt32Size(MedianLatencyCollectionIntervalMillis);
+      }
       if (_unknownFields != null) {
       if (_unknownFields != null) {
         size += _unknownFields.CalculateSize();
         size += _unknownFields.CalculateSize();
       }
       }
@@ -1524,6 +1551,9 @@ namespace Grpc.Testing {
       if (other.UseCoalesceApi != false) {
       if (other.UseCoalesceApi != false) {
         UseCoalesceApi = other.UseCoalesceApi;
         UseCoalesceApi = other.UseCoalesceApi;
       }
       }
+      if (other.MedianLatencyCollectionIntervalMillis != 0) {
+        MedianLatencyCollectionIntervalMillis = other.MedianLatencyCollectionIntervalMillis;
+      }
       _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
       _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
     }
 
 
@@ -1616,6 +1646,10 @@ namespace Grpc.Testing {
             UseCoalesceApi = input.ReadBool();
             UseCoalesceApi = input.ReadBool();
             break;
             break;
           }
           }
+          case 160: {
+            MedianLatencyCollectionIntervalMillis = input.ReadInt32();
+            break;
+          }
         }
         }
       }
       }
     }
     }

+ 8 - 0
src/csharp/Grpc.IntegrationTesting/EmptyServiceGrpc.cs

@@ -80,6 +80,14 @@ namespace Grpc.Testing {
       return grpc::ServerServiceDefinition.CreateBuilder().Build();
       return grpc::ServerServiceDefinition.CreateBuilder().Build();
     }
     }
 
 
+    /// <summary>Register service method implementations with a service binder. Useful when customizing the service binding logic.
+    /// Note: this method is part of an experimental API that can change or be removed without any prior notice.</summary>
+    /// <param name="serviceBinder">Service methods will be bound by calling <c>AddMethod</c> on this object.</param>
+    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
+    public static void BindService(grpc::ServiceBinderBase serviceBinder, EmptyServiceBase serviceImpl)
+    {
+    }
+
   }
   }
 }
 }
 #endregion
 #endregion

+ 10 - 0
src/csharp/Grpc.IntegrationTesting/MetricsGrpc.cs

@@ -193,6 +193,16 @@ namespace Grpc.Testing {
           .AddMethod(__Method_GetGauge, serviceImpl.GetGauge).Build();
           .AddMethod(__Method_GetGauge, serviceImpl.GetGauge).Build();
     }
     }
 
 
+    /// <summary>Register service method implementations with a service binder. Useful when customizing the service binding logic.
+    /// Note: this method is part of an experimental API that can change or be removed without any prior notice.</summary>
+    /// <param name="serviceBinder">Service methods will be bound by calling <c>AddMethod</c> on this object.</param>
+    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
+    public static void BindService(grpc::ServiceBinderBase serviceBinder, MetricsServiceBase serviceImpl)
+    {
+      serviceBinder.AddMethod(__Method_GetAllGauges, serviceImpl.GetAllGauges);
+      serviceBinder.AddMethod(__Method_GetGauge, serviceImpl.GetGauge);
+    }
+
   }
   }
 }
 }
 #endregion
 #endregion

+ 9 - 0
src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs

@@ -143,6 +143,15 @@ namespace Grpc.Testing {
           .AddMethod(__Method_ReportScenario, serviceImpl.ReportScenario).Build();
           .AddMethod(__Method_ReportScenario, serviceImpl.ReportScenario).Build();
     }
     }
 
 
+    /// <summary>Register service method implementations with a service binder. Useful when customizing the service binding logic.
+    /// Note: this method is part of an experimental API that can change or be removed without any prior notice.</summary>
+    /// <param name="serviceBinder">Service methods will be bound by calling <c>AddMethod</c> on this object.</param>
+    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
+    public static void BindService(grpc::ServiceBinderBase serviceBinder, ReportQpsScenarioServiceBase serviceImpl)
+    {
+      serviceBinder.AddMethod(__Method_ReportScenario, serviceImpl.ReportScenario);
+    }
+
   }
   }
 }
 }
 #endregion
 #endregion

+ 35 - 0
src/csharp/Grpc.IntegrationTesting/TestGrpc.cs

@@ -539,6 +539,22 @@ namespace Grpc.Testing {
           .AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall).Build();
           .AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall).Build();
     }
     }
 
 
+    /// <summary>Register service method implementations with a service binder. Useful when customizing the service binding logic.
+    /// Note: this method is part of an experimental API that can change or be removed without any prior notice.</summary>
+    /// <param name="serviceBinder">Service methods will be bound by calling <c>AddMethod</c> on this object.</param>
+    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
+    public static void BindService(grpc::ServiceBinderBase serviceBinder, TestServiceBase serviceImpl)
+    {
+      serviceBinder.AddMethod(__Method_EmptyCall, serviceImpl.EmptyCall);
+      serviceBinder.AddMethod(__Method_UnaryCall, serviceImpl.UnaryCall);
+      serviceBinder.AddMethod(__Method_CacheableUnaryCall, serviceImpl.CacheableUnaryCall);
+      serviceBinder.AddMethod(__Method_StreamingOutputCall, serviceImpl.StreamingOutputCall);
+      serviceBinder.AddMethod(__Method_StreamingInputCall, serviceImpl.StreamingInputCall);
+      serviceBinder.AddMethod(__Method_FullDuplexCall, serviceImpl.FullDuplexCall);
+      serviceBinder.AddMethod(__Method_HalfDuplexCall, serviceImpl.HalfDuplexCall);
+      serviceBinder.AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall);
+    }
+
   }
   }
   /// <summary>
   /// <summary>
   /// A simple service NOT implemented at servers so clients can test for
   /// A simple service NOT implemented at servers so clients can test for
@@ -661,6 +677,15 @@ namespace Grpc.Testing {
           .AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall).Build();
           .AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall).Build();
     }
     }
 
 
+    /// <summary>Register service method implementations with a service binder. Useful when customizing the service binding logic.
+    /// Note: this method is part of an experimental API that can change or be removed without any prior notice.</summary>
+    /// <param name="serviceBinder">Service methods will be bound by calling <c>AddMethod</c> on this object.</param>
+    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
+    public static void BindService(grpc::ServiceBinderBase serviceBinder, UnimplementedServiceBase serviceImpl)
+    {
+      serviceBinder.AddMethod(__Method_UnimplementedCall, serviceImpl.UnimplementedCall);
+    }
+
   }
   }
   /// <summary>
   /// <summary>
   /// A service used to control reconnect server.
   /// A service used to control reconnect server.
@@ -779,6 +804,16 @@ namespace Grpc.Testing {
           .AddMethod(__Method_Stop, serviceImpl.Stop).Build();
           .AddMethod(__Method_Stop, serviceImpl.Stop).Build();
     }
     }
 
 
+    /// <summary>Register service method implementations with a service binder. Useful when customizing the service binding logic.
+    /// Note: this method is part of an experimental API that can change or be removed without any prior notice.</summary>
+    /// <param name="serviceBinder">Service methods will be bound by calling <c>AddMethod</c> on this object.</param>
+    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
+    public static void BindService(grpc::ServiceBinderBase serviceBinder, ReconnectServiceBase serviceImpl)
+    {
+      serviceBinder.AddMethod(__Method_Start, serviceImpl.Start);
+      serviceBinder.AddMethod(__Method_Stop, serviceImpl.Stop);
+    }
+
   }
   }
 }
 }
 #endregion
 #endregion

+ 12 - 0
src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs

@@ -321,6 +321,18 @@ namespace Grpc.Testing {
           .AddMethod(__Method_QuitWorker, serviceImpl.QuitWorker).Build();
           .AddMethod(__Method_QuitWorker, serviceImpl.QuitWorker).Build();
     }
     }
 
 
+    /// <summary>Register service method implementations with a service binder. Useful when customizing the service binding logic.
+    /// Note: this method is part of an experimental API that can change or be removed without any prior notice.</summary>
+    /// <param name="serviceBinder">Service methods will be bound by calling <c>AddMethod</c> on this object.</param>
+    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
+    public static void BindService(grpc::ServiceBinderBase serviceBinder, WorkerServiceBase serviceImpl)
+    {
+      serviceBinder.AddMethod(__Method_RunServer, serviceImpl.RunServer);
+      serviceBinder.AddMethod(__Method_RunClient, serviceImpl.RunClient);
+      serviceBinder.AddMethod(__Method_CoreCount, serviceImpl.CoreCount);
+      serviceBinder.AddMethod(__Method_QuitWorker, serviceImpl.QuitWorker);
+    }
+
   }
   }
 }
 }
 #endregion
 #endregion

+ 9 - 0
src/csharp/Grpc.Reflection/ReflectionGrpc.cs

@@ -123,6 +123,15 @@ namespace Grpc.Reflection.V1Alpha {
           .AddMethod(__Method_ServerReflectionInfo, serviceImpl.ServerReflectionInfo).Build();
           .AddMethod(__Method_ServerReflectionInfo, serviceImpl.ServerReflectionInfo).Build();
     }
     }
 
 
+    /// <summary>Register service method implementations with a service binder. Useful when customizing the service binding logic.
+    /// Note: this method is part of an experimental API that can change or be removed without any prior notice.</summary>
+    /// <param name="serviceBinder">Service methods will be bound by calling <c>AddMethod</c> on this object.</param>
+    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
+    public static void BindService(grpc::ServiceBinderBase serviceBinder, ServerReflectionBase serviceImpl)
+    {
+      serviceBinder.AddMethod(__Method_ServerReflectionInfo, serviceImpl.ServerReflectionInfo);
+    }
+
   }
   }
 }
 }
 #endregion
 #endregion

+ 1 - 1
src/csharp/build_packages_dotnetcli.bat

@@ -13,7 +13,7 @@
 @rem limitations under the License.
 @rem limitations under the License.
 
 
 @rem Current package versions
 @rem Current package versions
-set VERSION=1.17.0-dev
+set VERSION=1.18.0-dev
 
 
 @rem Adjust the location of nuget.exe
 @rem Adjust the location of nuget.exe
 set NUGET=C:\nuget\nuget.exe
 set NUGET=C:\nuget\nuget.exe

+ 1 - 1
src/csharp/build_unitypackage.bat

@@ -13,7 +13,7 @@
 @rem limitations under the License.
 @rem limitations under the License.
 
 
 @rem Current package versions
 @rem Current package versions
-set VERSION=1.17.0-dev
+set VERSION=1.18.0-dev
 
 
 @rem Adjust the location of nuget.exe
 @rem Adjust the location of nuget.exe
 set NUGET=C:\nuget\nuget.exe
 set NUGET=C:\nuget\nuget.exe

+ 1 - 1
src/objective-c/!ProtoCompiler-gRPCPlugin.podspec

@@ -42,7 +42,7 @@ Pod::Spec.new do |s|
   # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed
   # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed
   # before them.
   # before them.
   s.name     = '!ProtoCompiler-gRPCPlugin'
   s.name     = '!ProtoCompiler-gRPCPlugin'
-  v = '1.17.0-dev'
+  v = '1.18.0-dev'
   s.version  = v
   s.version  = v
   s.summary  = 'The gRPC ProtoC plugin generates Objective-C files from .proto services.'
   s.summary  = 'The gRPC ProtoC plugin generates Objective-C files from .proto services.'
   s.description = <<-DESC
   s.description = <<-DESC

+ 1 - 1
src/objective-c/GRPCClient/private/version.h

@@ -22,4 +22,4 @@
 // instead. This file can be regenerated from the template by running
 // instead. This file can be regenerated from the template by running
 // `tools/buildgen/generate_projects.sh`.
 // `tools/buildgen/generate_projects.sh`.
 
 
-#define GRPC_OBJC_VERSION_STRING @"1.17.0-dev"
+#define GRPC_OBJC_VERSION_STRING @"1.18.0-dev"

+ 1 - 1
src/objective-c/tests/version.h

@@ -22,5 +22,5 @@
 // instead. This file can be regenerated from the template by running
 // instead. This file can be regenerated from the template by running
 // `tools/buildgen/generate_projects.sh`.
 // `tools/buildgen/generate_projects.sh`.
 
 
-#define GRPC_OBJC_VERSION_STRING @"1.17.0-dev"
+#define GRPC_OBJC_VERSION_STRING @"1.18.0-dev"
 #define GRPC_C_VERSION_STRING @"7.0.0-dev"
 #define GRPC_C_VERSION_STRING @"7.0.0-dev"

+ 1 - 1
src/php/composer.json

@@ -2,7 +2,7 @@
   "name": "grpc/grpc-dev",
   "name": "grpc/grpc-dev",
   "description": "gRPC library for PHP - for Developement use only",
   "description": "gRPC library for PHP - for Developement use only",
   "license": "Apache-2.0",
   "license": "Apache-2.0",
-  "version": "1.17.0",
+  "version": "1.18.0",
   "require": {
   "require": {
     "php": ">=5.5.0",
     "php": ">=5.5.0",
     "google/protobuf": "^v3.3.0"
     "google/protobuf": "^v3.3.0"

+ 2 - 0
src/php/ext/grpc/channel.c

@@ -393,6 +393,8 @@ PHP_METHOD(Channel, __construct) {
   channel->wrapper->target = strdup(target);
   channel->wrapper->target = strdup(target);
   channel->wrapper->args_hashstr = strdup(sha1str);
   channel->wrapper->args_hashstr = strdup(sha1str);
   channel->wrapper->creds_hashstr = NULL;
   channel->wrapper->creds_hashstr = NULL;
+  channel->wrapper->creds = creds;
+  channel->wrapper->args = args;
   if (creds != NULL && creds->hashstr != NULL) {
   if (creds != NULL && creds->hashstr != NULL) {
     php_grpc_int creds_hashstr_len = strlen(creds->hashstr);
     php_grpc_int creds_hashstr_len = strlen(creds->hashstr);
     char *channel_creds_hashstr = malloc(creds_hashstr_len + 1);
     char *channel_creds_hashstr = malloc(creds_hashstr_len + 1);

+ 3 - 0
src/php/ext/grpc/channel.h

@@ -19,6 +19,7 @@
 #ifndef NET_GRPC_PHP_GRPC_CHANNEL_H_
 #ifndef NET_GRPC_PHP_GRPC_CHANNEL_H_
 #define NET_GRPC_PHP_GRPC_CHANNEL_H_
 #define NET_GRPC_PHP_GRPC_CHANNEL_H_
 
 
+#include "channel_credentials.h"
 #include "php_grpc.h"
 #include "php_grpc.h"
 
 
 /* Class entry for the PHP Channel class */
 /* Class entry for the PHP Channel class */
@@ -32,6 +33,8 @@ typedef struct _grpc_channel_wrapper {
   char *creds_hashstr;
   char *creds_hashstr;
   size_t ref_count;
   size_t ref_count;
   gpr_mu mu;
   gpr_mu mu;
+  grpc_channel_args args;
+  wrapped_grpc_channel_credentials *creds;
 } grpc_channel_wrapper;
 } grpc_channel_wrapper;
 
 
 /* Wrapper struct for grpc_channel that can be associated with a PHP object */
 /* Wrapper struct for grpc_channel that can be associated with a PHP object */

+ 1 - 1
src/php/ext/grpc/config.m4

@@ -103,7 +103,7 @@ if test "$PHP_COVERAGE" = "yes"; then
     AC_MSG_ERROR([ccache must be disabled when --enable-coverage option is used. You can disable ccache by setting environment variable CCACHE_DISABLE=1.])
     AC_MSG_ERROR([ccache must be disabled when --enable-coverage option is used. You can disable ccache by setting environment variable CCACHE_DISABLE=1.])
   fi
   fi
   
   
-  lcov_version_list="1.5 1.6 1.7 1.9 1.10 1.11"
+  lcov_version_list="1.5 1.6 1.7 1.9 1.10 1.11 1.12 1.13"
 
 
   AC_CHECK_PROG(LCOV, lcov, lcov)
   AC_CHECK_PROG(LCOV, lcov, lcov)
   AC_CHECK_PROG(GENHTML, genhtml, genhtml)
   AC_CHECK_PROG(GENHTML, genhtml, genhtml)

+ 120 - 0
src/php/ext/grpc/php_grpc.c

@@ -26,6 +26,8 @@
 #include "call_credentials.h"
 #include "call_credentials.h"
 #include "server_credentials.h"
 #include "server_credentials.h"
 #include "completion_queue.h"
 #include "completion_queue.h"
+#include <ext/spl/spl_exceptions.h>
+#include <zend_exceptions.h>
 
 
 ZEND_DECLARE_MODULE_GLOBALS(grpc)
 ZEND_DECLARE_MODULE_GLOBALS(grpc)
 static PHP_GINIT_FUNCTION(grpc);
 static PHP_GINIT_FUNCTION(grpc);
@@ -86,6 +88,123 @@ ZEND_GET_MODULE(grpc)
    }
    }
 */
 */
 /* }}} */
 /* }}} */
+void create_new_channel(
+    wrapped_grpc_channel *channel,
+    char *target,
+    grpc_channel_args args,
+    wrapped_grpc_channel_credentials *creds) {
+  if (creds == NULL) {
+    channel->wrapper->wrapped = grpc_insecure_channel_create(target, &args,
+                                                             NULL);
+  } else {
+    channel->wrapper->wrapped =
+        grpc_secure_channel_create(creds->wrapped, target, &args, NULL);
+  }
+}
+
+void acquire_persistent_locks() {
+  zval *data;
+  PHP_GRPC_HASH_FOREACH_VAL_START(&grpc_persistent_list, data)
+    php_grpc_zend_resource *rsrc  =
+                (php_grpc_zend_resource*) PHP_GRPC_HASH_VALPTR_TO_VAL(data)
+    if (rsrc == NULL) {
+      break;
+    }
+    channel_persistent_le_t* le = rsrc->ptr;
+
+    gpr_mu_lock(&le->channel->mu);
+  PHP_GRPC_HASH_FOREACH_END()
+}
+
+void release_persistent_locks() {
+  zval *data;
+  PHP_GRPC_HASH_FOREACH_VAL_START(&grpc_persistent_list, data)
+    php_grpc_zend_resource *rsrc  =
+                (php_grpc_zend_resource*) PHP_GRPC_HASH_VALPTR_TO_VAL(data)
+    if (rsrc == NULL) {
+      break;
+    }
+    channel_persistent_le_t* le = rsrc->ptr;
+
+    gpr_mu_unlock(&le->channel->mu);
+  PHP_GRPC_HASH_FOREACH_END()
+}
+
+void destroy_grpc_channels() {
+  zval *data;
+  PHP_GRPC_HASH_FOREACH_VAL_START(&grpc_persistent_list, data)
+    php_grpc_zend_resource *rsrc  =
+                (php_grpc_zend_resource*) PHP_GRPC_HASH_VALPTR_TO_VAL(data)
+    if (rsrc == NULL) {
+      break;
+    }
+    channel_persistent_le_t* le = rsrc->ptr;
+
+    wrapped_grpc_channel wrapped_channel;
+    wrapped_channel.wrapper = le->channel;
+    grpc_channel_wrapper *channel = wrapped_channel.wrapper;
+    grpc_channel_destroy(channel->wrapped);
+  PHP_GRPC_HASH_FOREACH_END()
+}
+
+void restart_channels() {
+  zval *data;
+  PHP_GRPC_HASH_FOREACH_VAL_START(&grpc_persistent_list, data)
+    php_grpc_zend_resource *rsrc  =
+                (php_grpc_zend_resource*) PHP_GRPC_HASH_VALPTR_TO_VAL(data)
+    if (rsrc == NULL) {
+      break;
+    }
+    channel_persistent_le_t* le = rsrc->ptr;
+
+    wrapped_grpc_channel wrapped_channel;
+    wrapped_channel.wrapper = le->channel;
+    grpc_channel_wrapper *channel = wrapped_channel.wrapper;
+    create_new_channel(&wrapped_channel, channel->target, channel->args,
+                       channel->creds);
+    gpr_mu_unlock(&channel->mu);
+  PHP_GRPC_HASH_FOREACH_END()
+}
+
+void prefork() {
+  acquire_persistent_locks();
+}
+
+void postfork_child() {
+  // loop through persistant list and destroy all underlying grpc_channel objs
+  destroy_grpc_channels();
+
+  // clear completion queue
+  grpc_php_shutdown_completion_queue();
+
+  // clean-up grpc_core
+  grpc_shutdown();
+  if (grpc_is_initialized() > 0) {
+    zend_throw_exception(spl_ce_UnexpectedValueException,
+                         "Oops, failed to shutdown gRPC Core after fork()",
+                         1 TSRMLS_CC);
+  }
+
+  // restart grpc_core
+  grpc_init();
+  grpc_php_init_completion_queue();
+
+  // re-create grpc_channel and point wrapped to it
+  // unlock wrapped grpc channel mutex
+  restart_channels();
+}
+
+void postfork_parent() {
+  release_persistent_locks();
+}
+
+void register_fork_handlers() {
+  if (getenv("GRPC_ENABLE_FORK_SUPPORT")) {
+#ifdef GRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK
+    pthread_atfork(&prefork, &postfork_parent, &postfork_child);
+#endif  // GRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK
+  }
+}
 
 
 /* {{{ PHP_MINIT_FUNCTION
 /* {{{ PHP_MINIT_FUNCTION
  */
  */
@@ -265,6 +384,7 @@ PHP_MINFO_FUNCTION(grpc) {
 PHP_RINIT_FUNCTION(grpc) {
 PHP_RINIT_FUNCTION(grpc) {
   if (!GRPC_G(initialized)) {
   if (!GRPC_G(initialized)) {
     grpc_init();
     grpc_init();
+    register_fork_handlers();
     grpc_php_init_completion_queue(TSRMLS_C);
     grpc_php_init_completion_queue(TSRMLS_C);
     GRPC_G(initialized) = 1;
     GRPC_G(initialized) = 1;
   }
   }

+ 1 - 1
src/php/ext/grpc/version.h

@@ -20,6 +20,6 @@
 #ifndef VERSION_H
 #ifndef VERSION_H
 #define VERSION_H
 #define VERSION_H
 
 
-#define PHP_GRPC_VERSION "1.17.0dev"
+#define PHP_GRPC_VERSION "1.18.0dev"
 
 
 #endif /* VERSION_H */
 #endif /* VERSION_H */

+ 1 - 1
src/python/grpcio/grpc/_grpcio_metadata.py

@@ -14,4 +14,4 @@
 
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc/_grpcio_metadata.py.template`!!!
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc/_grpcio_metadata.py.template`!!!
 
 
-__version__ = """1.17.0.dev0"""
+__version__ = """1.18.0.dev0"""

+ 1 - 1
src/python/grpcio/grpc_core_dependencies.py

@@ -324,12 +324,12 @@ CORE_SOURCE_FILES = [
     'src/core/ext/filters/client_channel/lb_policy.cc',
     'src/core/ext/filters/client_channel/lb_policy.cc',
     'src/core/ext/filters/client_channel/lb_policy_factory.cc',
     'src/core/ext/filters/client_channel/lb_policy_factory.cc',
     'src/core/ext/filters/client_channel/lb_policy_registry.cc',
     'src/core/ext/filters/client_channel/lb_policy_registry.cc',
-    'src/core/ext/filters/client_channel/method_params.cc',
     'src/core/ext/filters/client_channel/parse_address.cc',
     'src/core/ext/filters/client_channel/parse_address.cc',
     'src/core/ext/filters/client_channel/proxy_mapper.cc',
     'src/core/ext/filters/client_channel/proxy_mapper.cc',
     'src/core/ext/filters/client_channel/proxy_mapper_registry.cc',
     'src/core/ext/filters/client_channel/proxy_mapper_registry.cc',
     'src/core/ext/filters/client_channel/resolver.cc',
     'src/core/ext/filters/client_channel/resolver.cc',
     'src/core/ext/filters/client_channel/resolver_registry.cc',
     'src/core/ext/filters/client_channel/resolver_registry.cc',
+    'src/core/ext/filters/client_channel/resolver_result_parsing.cc',
     'src/core/ext/filters/client_channel/retry_throttle.cc',
     'src/core/ext/filters/client_channel/retry_throttle.cc',
     'src/core/ext/filters/client_channel/subchannel.cc',
     'src/core/ext/filters/client_channel/subchannel.cc',
     'src/core/ext/filters/client_channel/subchannel_index.cc',
     'src/core/ext/filters/client_channel/subchannel_index.cc',

+ 1 - 1
src/python/grpcio/grpc_version.py

@@ -14,4 +14,4 @@
 
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_version.py.template`!!!
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_version.py.template`!!!
 
 
-VERSION = '1.17.0.dev0'
+VERSION = '1.18.0.dev0'

+ 1 - 1
src/python/grpcio_health_checking/grpc_version.py

@@ -14,4 +14,4 @@
 
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_health_checking/grpc_version.py.template`!!!
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_health_checking/grpc_version.py.template`!!!
 
 
-VERSION = '1.17.0.dev0'
+VERSION = '1.18.0.dev0'

+ 1 - 1
src/python/grpcio_reflection/grpc_version.py

@@ -14,4 +14,4 @@
 
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_reflection/grpc_version.py.template`!!!
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_reflection/grpc_version.py.template`!!!
 
 
-VERSION = '1.17.0.dev0'
+VERSION = '1.18.0.dev0'

+ 1 - 1
src/python/grpcio_testing/grpc_version.py

@@ -14,4 +14,4 @@
 
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_testing/grpc_version.py.template`!!!
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_testing/grpc_version.py.template`!!!
 
 
-VERSION = '1.17.0.dev0'
+VERSION = '1.18.0.dev0'

+ 1 - 1
src/python/grpcio_tests/grpc_version.py

@@ -14,4 +14,4 @@
 
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_tests/grpc_version.py.template`!!!
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_tests/grpc_version.py.template`!!!
 
 
-VERSION = '1.17.0.dev0'
+VERSION = '1.18.0.dev0'

+ 24 - 27
src/python/grpcio_tests/tests/unit/_server_ssl_cert_config_test.py

@@ -70,18 +70,11 @@ SERVER_CERT_CHAIN_2_PEM = (resources.cert_hier_2_server_1_cert() +
 Call = collections.namedtuple('Call', ['did_raise', 'returned_cert_config'])
 Call = collections.namedtuple('Call', ['did_raise', 'returned_cert_config'])
 
 
 
 
-def _create_client_stub(
-        port,
-        expect_success,
-        root_certificates=None,
-        private_key=None,
-        certificate_chain=None,
-):
-    channel = grpc.secure_channel('localhost:{}'.format(port),
-                                  grpc.ssl_channel_credentials(
-                                      root_certificates=root_certificates,
-                                      private_key=private_key,
-                                      certificate_chain=certificate_chain))
+def _create_channel(port, credentials):
+    return grpc.secure_channel('localhost:{}'.format(port), credentials)
+
+
+def _create_client_stub(channel, expect_success):
     if expect_success:
     if expect_success:
         # per Nathaniel: there's some robustness issue if we start
         # per Nathaniel: there's some robustness issue if we start
         # using a channel without waiting for it to be actually ready
         # using a channel without waiting for it to be actually ready
@@ -176,14 +169,13 @@ class _ServerSSLCertReloadTest(
                                 root_certificates=None,
                                 root_certificates=None,
                                 private_key=None,
                                 private_key=None,
                                 certificate_chain=None):
                                 certificate_chain=None):
-        client_stub = _create_client_stub(
-            self.port,
-            expect_success,
+        credentials = grpc.ssl_channel_credentials(
             root_certificates=root_certificates,
             root_certificates=root_certificates,
             private_key=private_key,
             private_key=private_key,
             certificate_chain=certificate_chain)
             certificate_chain=certificate_chain)
-        self._perform_rpc(client_stub, expect_success)
-        del client_stub
+        with _create_channel(self.port, credentials) as client_channel:
+            client_stub = _create_client_stub(client_channel, expect_success)
+            self._perform_rpc(client_stub, expect_success)
 
 
     def _test(self):
     def _test(self):
         # things should work...
         # things should work...
@@ -259,12 +251,13 @@ class _ServerSSLCertReloadTest(
         # now create the "persistent" clients
         # now create the "persistent" clients
         self.cert_config_fetcher.reset()
         self.cert_config_fetcher.reset()
         self.cert_config_fetcher.configure(False, None)
         self.cert_config_fetcher.configure(False, None)
-        persistent_client_stub_A = _create_client_stub(
+        channel_A = _create_channel(
             self.port,
             self.port,
-            True,
-            root_certificates=CA_1_PEM,
-            private_key=CLIENT_KEY_2_PEM,
-            certificate_chain=CLIENT_CERT_CHAIN_2_PEM)
+            grpc.ssl_channel_credentials(
+                root_certificates=CA_1_PEM,
+                private_key=CLIENT_KEY_2_PEM,
+                certificate_chain=CLIENT_CERT_CHAIN_2_PEM))
+        persistent_client_stub_A = _create_client_stub(channel_A, True)
         self._perform_rpc(persistent_client_stub_A, True)
         self._perform_rpc(persistent_client_stub_A, True)
         actual_calls = self.cert_config_fetcher.getCalls()
         actual_calls = self.cert_config_fetcher.getCalls()
         self.assertEqual(len(actual_calls), 1)
         self.assertEqual(len(actual_calls), 1)
@@ -273,12 +266,13 @@ class _ServerSSLCertReloadTest(
 
 
         self.cert_config_fetcher.reset()
         self.cert_config_fetcher.reset()
         self.cert_config_fetcher.configure(False, None)
         self.cert_config_fetcher.configure(False, None)
-        persistent_client_stub_B = _create_client_stub(
+        channel_B = _create_channel(
             self.port,
             self.port,
-            True,
-            root_certificates=CA_1_PEM,
-            private_key=CLIENT_KEY_2_PEM,
-            certificate_chain=CLIENT_CERT_CHAIN_2_PEM)
+            grpc.ssl_channel_credentials(
+                root_certificates=CA_1_PEM,
+                private_key=CLIENT_KEY_2_PEM,
+                certificate_chain=CLIENT_CERT_CHAIN_2_PEM))
+        persistent_client_stub_B = _create_client_stub(channel_B, True)
         self._perform_rpc(persistent_client_stub_B, True)
         self._perform_rpc(persistent_client_stub_B, True)
         actual_calls = self.cert_config_fetcher.getCalls()
         actual_calls = self.cert_config_fetcher.getCalls()
         self.assertEqual(len(actual_calls), 1)
         self.assertEqual(len(actual_calls), 1)
@@ -359,6 +353,9 @@ class _ServerSSLCertReloadTest(
         actual_calls = self.cert_config_fetcher.getCalls()
         actual_calls = self.cert_config_fetcher.getCalls()
         self.assertEqual(len(actual_calls), 0)
         self.assertEqual(len(actual_calls), 0)
 
 
+        channel_A.close()
+        channel_B.close()
+
 
 
 class ServerSSLCertConfigFetcherParamsChecks(unittest.TestCase):
 class ServerSSLCertConfigFetcherParamsChecks(unittest.TestCase):
 
 

+ 1 - 1
src/ruby/lib/grpc/version.rb

@@ -14,5 +14,5 @@
 
 
 # GRPC contains the General RPC module.
 # GRPC contains the General RPC module.
 module GRPC
 module GRPC
-  VERSION = '1.17.0.dev'
+  VERSION = '1.18.0.dev'
 end
 end

+ 1 - 1
src/ruby/tools/version.rb

@@ -14,6 +14,6 @@
 
 
 module GRPC
 module GRPC
   module Tools
   module Tools
-    VERSION = '1.17.0.dev'
+    VERSION = '1.18.0.dev'
   end
   end
 end
 end

+ 1 - 1
templates/Makefile.template

@@ -1370,7 +1370,7 @@
   ifeq ($(SYSTEM),MINGW32)
   ifeq ($(SYSTEM),MINGW32)
   	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/lib${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]})-dll.a $(prefix)/lib/lib${lib.name}.a
   	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/lib${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]})-dll.a $(prefix)/lib/lib${lib.name}.a
   else ifneq ($(SYSTEM),Darwin)
   else ifneq ($(SYSTEM),Darwin)
-  	$(Q) ln -sf $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]}) $(prefix)/lib/lib${lib.name}.so.${settings.core_version.major}
+  	$(Q) ln -sf $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]}) $(prefix)/lib/lib${lib.name}.so.${settings.get(lang_to_var[lib.language].lower() + '_version').major}
   	$(Q) ln -sf $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]}) $(prefix)/lib/lib${lib.name}.so
   	$(Q) ln -sf $(SHARED_PREFIX)${lib.name}$(SHARED_VERSION_${lang_to_var[lib.language]}).$(SHARED_EXT_${lang_to_var[lib.language]}) $(prefix)/lib/lib${lib.name}.so
   endif
   endif
   % endif
   % endif

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