Merge remote-tracking branch 'upstream/master' into circular_dependency_fix

pull/8517/head
Mark D. Roth 9 years ago
commit e4e457ed76
  1. 8
      BUILD
  2. 3
      CMakeLists.txt
  3. 3
      Makefile
  4. 1
      binding.gyp
  5. 2
      build.yaml
  6. 1
      config.m4
  7. 3
      gRPC-Core.podspec
  8. 2
      grpc.gemspec
  9. 7
      include/grpc/impl/codegen/grpc_types.h
  10. 2
      package.xml
  11. 21
      src/core/ext/client_channel/README.md
  12. 59
      src/core/ext/client_channel/client_channel.c
  13. 4
      src/core/ext/client_channel/client_channel_factory.c
  14. 9
      src/core/ext/client_channel/client_channel_factory.h
  15. 78
      src/core/ext/client_channel/lb_policy_factory.c
  16. 40
      src/core/ext/client_channel/lb_policy_factory.h
  17. 3
      src/core/ext/client_channel/resolver.c
  18. 18
      src/core/ext/client_channel/resolver.h
  19. 7
      src/core/ext/client_channel/resolver_factory.h
  20. 12
      src/core/ext/client_channel/resolver_registry.c
  21. 7
      src/core/ext/client_channel/resolver_registry.h
  22. 94
      src/core/ext/client_channel/resolver_result.c
  23. 68
      src/core/ext/client_channel/resolver_result.h
  24. 2
      src/core/ext/client_channel/subchannel.c
  25. 2
      src/core/ext/client_channel/subchannel.h
  26. 6
      src/core/ext/client_channel/subchannel_index.c
  27. 4
      src/core/ext/client_channel/subchannel_index.h
  28. 106
      src/core/ext/lb_policy/grpclb/grpclb.c
  29. 30
      src/core/ext/lb_policy/pick_first/pick_first.c
  30. 29
      src/core/ext/lb_policy/round_robin/round_robin.c
  31. 50
      src/core/ext/resolver/dns/native/dns_resolver.c
  32. 35
      src/core/ext/resolver/sockaddr/sockaddr_resolver.c
  33. 63
      src/core/ext/transport/chttp2/client/insecure/channel_create.c
  34. 73
      src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
  35. 55
      src/core/lib/channel/channel_args.c
  36. 11
      src/core/lib/channel/channel_args.h
  37. 10
      src/csharp/Grpc.Core/Internal/SafeHandleZeroIsInvalid.cs
  38. 12
      src/csharp/Grpc.Core/Internal/ServerCallHandler.cs
  39. 9
      src/csharp/Grpc.Core/ServerCallContext.cs
  40. 1
      src/node/interop/interop_client.js
  41. 1
      src/python/grpcio/grpc_core_dependencies.py
  42. 5
      src/python/grpcio_tests/tests/interop/client.py
  43. 188
      src/python/grpcio_tests/tests/interop/methods.py
  44. 5
      test/core/client_channel/resolvers/dns_resolver_connectivity_test.c
  45. 14
      test/core/client_channel/resolvers/sockaddr_resolver_test.c
  46. 42
      test/core/end2end/fake_resolver.c
  47. 2
      test/cpp/end2end/end2end_test.cc
  48. 2
      tools/doxygen/Doxyfile.core.internal
  49. 4
      tools/run_tests/run_interop_tests.py
  50. 3
      tools/run_tests/sources_and_headers.json
  51. 3
      vsprojects/vcxproj/grpc/grpc.vcxproj
  52. 6
      vsprojects/vcxproj/grpc/grpc.vcxproj.filters
  53. 3
      vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
  54. 6
      vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters

@ -311,7 +311,6 @@ cc_library(
"src/core/ext/client_channel/resolver.h", "src/core/ext/client_channel/resolver.h",
"src/core/ext/client_channel/resolver_factory.h", "src/core/ext/client_channel/resolver_factory.h",
"src/core/ext/client_channel/resolver_registry.h", "src/core/ext/client_channel/resolver_registry.h",
"src/core/ext/client_channel/resolver_result.h",
"src/core/ext/client_channel/subchannel.h", "src/core/ext/client_channel/subchannel.h",
"src/core/ext/client_channel/subchannel_index.h", "src/core/ext/client_channel/subchannel_index.h",
"src/core/ext/client_channel/uri_parser.h", "src/core/ext/client_channel/uri_parser.h",
@ -504,7 +503,6 @@ cc_library(
"src/core/ext/client_channel/resolver.c", "src/core/ext/client_channel/resolver.c",
"src/core/ext/client_channel/resolver_factory.c", "src/core/ext/client_channel/resolver_factory.c",
"src/core/ext/client_channel/resolver_registry.c", "src/core/ext/client_channel/resolver_registry.c",
"src/core/ext/client_channel/resolver_result.c",
"src/core/ext/client_channel/subchannel.c", "src/core/ext/client_channel/subchannel.c",
"src/core/ext/client_channel/subchannel_index.c", "src/core/ext/client_channel/subchannel_index.c",
"src/core/ext/client_channel/uri_parser.c", "src/core/ext/client_channel/uri_parser.c",
@ -711,7 +709,6 @@ cc_library(
"src/core/ext/client_channel/resolver.h", "src/core/ext/client_channel/resolver.h",
"src/core/ext/client_channel/resolver_factory.h", "src/core/ext/client_channel/resolver_factory.h",
"src/core/ext/client_channel/resolver_registry.h", "src/core/ext/client_channel/resolver_registry.h",
"src/core/ext/client_channel/resolver_result.h",
"src/core/ext/client_channel/subchannel.h", "src/core/ext/client_channel/subchannel.h",
"src/core/ext/client_channel/subchannel_index.h", "src/core/ext/client_channel/subchannel_index.h",
"src/core/ext/client_channel/uri_parser.h", "src/core/ext/client_channel/uri_parser.h",
@ -887,7 +884,6 @@ cc_library(
"src/core/ext/client_channel/resolver.c", "src/core/ext/client_channel/resolver.c",
"src/core/ext/client_channel/resolver_factory.c", "src/core/ext/client_channel/resolver_factory.c",
"src/core/ext/client_channel/resolver_registry.c", "src/core/ext/client_channel/resolver_registry.c",
"src/core/ext/client_channel/resolver_result.c",
"src/core/ext/client_channel/subchannel.c", "src/core/ext/client_channel/subchannel.c",
"src/core/ext/client_channel/subchannel_index.c", "src/core/ext/client_channel/subchannel_index.c",
"src/core/ext/client_channel/uri_parser.c", "src/core/ext/client_channel/uri_parser.c",
@ -1088,7 +1084,6 @@ cc_library(
"src/core/ext/client_channel/resolver.h", "src/core/ext/client_channel/resolver.h",
"src/core/ext/client_channel/resolver_factory.h", "src/core/ext/client_channel/resolver_factory.h",
"src/core/ext/client_channel/resolver_registry.h", "src/core/ext/client_channel/resolver_registry.h",
"src/core/ext/client_channel/resolver_result.h",
"src/core/ext/client_channel/subchannel.h", "src/core/ext/client_channel/subchannel.h",
"src/core/ext/client_channel/subchannel_index.h", "src/core/ext/client_channel/subchannel_index.h",
"src/core/ext/client_channel/uri_parser.h", "src/core/ext/client_channel/uri_parser.h",
@ -1257,7 +1252,6 @@ cc_library(
"src/core/ext/client_channel/resolver.c", "src/core/ext/client_channel/resolver.c",
"src/core/ext/client_channel/resolver_factory.c", "src/core/ext/client_channel/resolver_factory.c",
"src/core/ext/client_channel/resolver_registry.c", "src/core/ext/client_channel/resolver_registry.c",
"src/core/ext/client_channel/resolver_result.c",
"src/core/ext/client_channel/subchannel.c", "src/core/ext/client_channel/subchannel.c",
"src/core/ext/client_channel/subchannel_index.c", "src/core/ext/client_channel/subchannel_index.c",
"src/core/ext/client_channel/uri_parser.c", "src/core/ext/client_channel/uri_parser.c",
@ -2207,7 +2201,6 @@ objc_library(
"src/core/ext/client_channel/resolver.c", "src/core/ext/client_channel/resolver.c",
"src/core/ext/client_channel/resolver_factory.c", "src/core/ext/client_channel/resolver_factory.c",
"src/core/ext/client_channel/resolver_registry.c", "src/core/ext/client_channel/resolver_registry.c",
"src/core/ext/client_channel/resolver_result.c",
"src/core/ext/client_channel/subchannel.c", "src/core/ext/client_channel/subchannel.c",
"src/core/ext/client_channel/subchannel_index.c", "src/core/ext/client_channel/subchannel_index.c",
"src/core/ext/client_channel/uri_parser.c", "src/core/ext/client_channel/uri_parser.c",
@ -2416,7 +2409,6 @@ objc_library(
"src/core/ext/client_channel/resolver.h", "src/core/ext/client_channel/resolver.h",
"src/core/ext/client_channel/resolver_factory.h", "src/core/ext/client_channel/resolver_factory.h",
"src/core/ext/client_channel/resolver_registry.h", "src/core/ext/client_channel/resolver_registry.h",
"src/core/ext/client_channel/resolver_result.h",
"src/core/ext/client_channel/subchannel.h", "src/core/ext/client_channel/subchannel.h",
"src/core/ext/client_channel/subchannel_index.h", "src/core/ext/client_channel/subchannel_index.h",
"src/core/ext/client_channel/uri_parser.h", "src/core/ext/client_channel/uri_parser.h",

@ -462,7 +462,6 @@ add_library(grpc
src/core/ext/client_channel/resolver.c src/core/ext/client_channel/resolver.c
src/core/ext/client_channel/resolver_factory.c src/core/ext/client_channel/resolver_factory.c
src/core/ext/client_channel/resolver_registry.c src/core/ext/client_channel/resolver_registry.c
src/core/ext/client_channel/resolver_result.c
src/core/ext/client_channel/subchannel.c src/core/ext/client_channel/subchannel.c
src/core/ext/client_channel/subchannel_index.c src/core/ext/client_channel/subchannel_index.c
src/core/ext/client_channel/uri_parser.c src/core/ext/client_channel/uri_parser.c
@ -709,7 +708,6 @@ add_library(grpc_cronet
src/core/ext/client_channel/resolver.c src/core/ext/client_channel/resolver.c
src/core/ext/client_channel/resolver_factory.c src/core/ext/client_channel/resolver_factory.c
src/core/ext/client_channel/resolver_registry.c src/core/ext/client_channel/resolver_registry.c
src/core/ext/client_channel/resolver_result.c
src/core/ext/client_channel/subchannel.c src/core/ext/client_channel/subchannel.c
src/core/ext/client_channel/subchannel_index.c src/core/ext/client_channel/subchannel_index.c
src/core/ext/client_channel/uri_parser.c src/core/ext/client_channel/uri_parser.c
@ -953,7 +951,6 @@ add_library(grpc_unsecure
src/core/ext/client_channel/resolver.c src/core/ext/client_channel/resolver.c
src/core/ext/client_channel/resolver_factory.c src/core/ext/client_channel/resolver_factory.c
src/core/ext/client_channel/resolver_registry.c src/core/ext/client_channel/resolver_registry.c
src/core/ext/client_channel/resolver_result.c
src/core/ext/client_channel/subchannel.c src/core/ext/client_channel/subchannel.c
src/core/ext/client_channel/subchannel_index.c src/core/ext/client_channel/subchannel_index.c
src/core/ext/client_channel/uri_parser.c src/core/ext/client_channel/uri_parser.c

@ -2747,7 +2747,6 @@ LIBGRPC_SRC = \
src/core/ext/client_channel/resolver.c \ src/core/ext/client_channel/resolver.c \
src/core/ext/client_channel/resolver_factory.c \ src/core/ext/client_channel/resolver_factory.c \
src/core/ext/client_channel/resolver_registry.c \ src/core/ext/client_channel/resolver_registry.c \
src/core/ext/client_channel/resolver_result.c \
src/core/ext/client_channel/subchannel.c \ src/core/ext/client_channel/subchannel.c \
src/core/ext/client_channel/subchannel_index.c \ src/core/ext/client_channel/subchannel_index.c \
src/core/ext/client_channel/uri_parser.c \ src/core/ext/client_channel/uri_parser.c \
@ -3012,7 +3011,6 @@ LIBGRPC_CRONET_SRC = \
src/core/ext/client_channel/resolver.c \ src/core/ext/client_channel/resolver.c \
src/core/ext/client_channel/resolver_factory.c \ src/core/ext/client_channel/resolver_factory.c \
src/core/ext/client_channel/resolver_registry.c \ src/core/ext/client_channel/resolver_registry.c \
src/core/ext/client_channel/resolver_result.c \
src/core/ext/client_channel/subchannel.c \ src/core/ext/client_channel/subchannel.c \
src/core/ext/client_channel/subchannel_index.c \ src/core/ext/client_channel/subchannel_index.c \
src/core/ext/client_channel/uri_parser.c \ src/core/ext/client_channel/uri_parser.c \
@ -3502,7 +3500,6 @@ LIBGRPC_UNSECURE_SRC = \
src/core/ext/client_channel/resolver.c \ src/core/ext/client_channel/resolver.c \
src/core/ext/client_channel/resolver_factory.c \ src/core/ext/client_channel/resolver_factory.c \
src/core/ext/client_channel/resolver_registry.c \ src/core/ext/client_channel/resolver_registry.c \
src/core/ext/client_channel/resolver_result.c \
src/core/ext/client_channel/subchannel.c \ src/core/ext/client_channel/subchannel.c \
src/core/ext/client_channel/subchannel_index.c \ src/core/ext/client_channel/subchannel_index.c \
src/core/ext/client_channel/uri_parser.c \ src/core/ext/client_channel/uri_parser.c \

@ -740,7 +740,6 @@
'src/core/ext/client_channel/resolver.c', 'src/core/ext/client_channel/resolver.c',
'src/core/ext/client_channel/resolver_factory.c', 'src/core/ext/client_channel/resolver_factory.c',
'src/core/ext/client_channel/resolver_registry.c', 'src/core/ext/client_channel/resolver_registry.c',
'src/core/ext/client_channel/resolver_result.c',
'src/core/ext/client_channel/subchannel.c', 'src/core/ext/client_channel/subchannel.c',
'src/core/ext/client_channel/subchannel_index.c', 'src/core/ext/client_channel/subchannel_index.c',
'src/core/ext/client_channel/uri_parser.c', 'src/core/ext/client_channel/uri_parser.c',

@ -383,7 +383,6 @@ filegroups:
- src/core/ext/client_channel/resolver.h - src/core/ext/client_channel/resolver.h
- src/core/ext/client_channel/resolver_factory.h - src/core/ext/client_channel/resolver_factory.h
- src/core/ext/client_channel/resolver_registry.h - src/core/ext/client_channel/resolver_registry.h
- src/core/ext/client_channel/resolver_result.h
- src/core/ext/client_channel/subchannel.h - src/core/ext/client_channel/subchannel.h
- src/core/ext/client_channel/subchannel_index.h - src/core/ext/client_channel/subchannel_index.h
- src/core/ext/client_channel/uri_parser.h - src/core/ext/client_channel/uri_parser.h
@ -403,7 +402,6 @@ filegroups:
- src/core/ext/client_channel/resolver.c - src/core/ext/client_channel/resolver.c
- src/core/ext/client_channel/resolver_factory.c - src/core/ext/client_channel/resolver_factory.c
- src/core/ext/client_channel/resolver_registry.c - src/core/ext/client_channel/resolver_registry.c
- src/core/ext/client_channel/resolver_result.c
- src/core/ext/client_channel/subchannel.c - src/core/ext/client_channel/subchannel.c
- src/core/ext/client_channel/subchannel_index.c - src/core/ext/client_channel/subchannel_index.c
- src/core/ext/client_channel/uri_parser.c - src/core/ext/client_channel/uri_parser.c

@ -256,7 +256,6 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/client_channel/resolver.c \ src/core/ext/client_channel/resolver.c \
src/core/ext/client_channel/resolver_factory.c \ src/core/ext/client_channel/resolver_factory.c \
src/core/ext/client_channel/resolver_registry.c \ src/core/ext/client_channel/resolver_registry.c \
src/core/ext/client_channel/resolver_result.c \
src/core/ext/client_channel/subchannel.c \ src/core/ext/client_channel/subchannel.c \
src/core/ext/client_channel/subchannel_index.c \ src/core/ext/client_channel/subchannel_index.c \
src/core/ext/client_channel/uri_parser.c \ src/core/ext/client_channel/uri_parser.c \

@ -398,7 +398,6 @@ Pod::Spec.new do |s|
'src/core/ext/client_channel/resolver.h', 'src/core/ext/client_channel/resolver.h',
'src/core/ext/client_channel/resolver_factory.h', 'src/core/ext/client_channel/resolver_factory.h',
'src/core/ext/client_channel/resolver_registry.h', 'src/core/ext/client_channel/resolver_registry.h',
'src/core/ext/client_channel/resolver_result.h',
'src/core/ext/client_channel/subchannel.h', 'src/core/ext/client_channel/subchannel.h',
'src/core/ext/client_channel/subchannel_index.h', 'src/core/ext/client_channel/subchannel_index.h',
'src/core/ext/client_channel/uri_parser.h', 'src/core/ext/client_channel/uri_parser.h',
@ -595,7 +594,6 @@ Pod::Spec.new do |s|
'src/core/ext/client_channel/resolver.c', 'src/core/ext/client_channel/resolver.c',
'src/core/ext/client_channel/resolver_factory.c', 'src/core/ext/client_channel/resolver_factory.c',
'src/core/ext/client_channel/resolver_registry.c', 'src/core/ext/client_channel/resolver_registry.c',
'src/core/ext/client_channel/resolver_result.c',
'src/core/ext/client_channel/subchannel.c', 'src/core/ext/client_channel/subchannel.c',
'src/core/ext/client_channel/subchannel_index.c', 'src/core/ext/client_channel/subchannel_index.c',
'src/core/ext/client_channel/uri_parser.c', 'src/core/ext/client_channel/uri_parser.c',
@ -793,7 +791,6 @@ Pod::Spec.new do |s|
'src/core/ext/client_channel/resolver.h', 'src/core/ext/client_channel/resolver.h',
'src/core/ext/client_channel/resolver_factory.h', 'src/core/ext/client_channel/resolver_factory.h',
'src/core/ext/client_channel/resolver_registry.h', 'src/core/ext/client_channel/resolver_registry.h',
'src/core/ext/client_channel/resolver_result.h',
'src/core/ext/client_channel/subchannel.h', 'src/core/ext/client_channel/subchannel.h',
'src/core/ext/client_channel/subchannel_index.h', 'src/core/ext/client_channel/subchannel_index.h',
'src/core/ext/client_channel/uri_parser.h', 'src/core/ext/client_channel/uri_parser.h',

@ -318,7 +318,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/client_channel/resolver.h ) s.files += %w( src/core/ext/client_channel/resolver.h )
s.files += %w( src/core/ext/client_channel/resolver_factory.h ) s.files += %w( src/core/ext/client_channel/resolver_factory.h )
s.files += %w( src/core/ext/client_channel/resolver_registry.h ) s.files += %w( src/core/ext/client_channel/resolver_registry.h )
s.files += %w( src/core/ext/client_channel/resolver_result.h )
s.files += %w( src/core/ext/client_channel/subchannel.h ) s.files += %w( src/core/ext/client_channel/subchannel.h )
s.files += %w( src/core/ext/client_channel/subchannel_index.h ) s.files += %w( src/core/ext/client_channel/subchannel_index.h )
s.files += %w( src/core/ext/client_channel/uri_parser.h ) s.files += %w( src/core/ext/client_channel/uri_parser.h )
@ -515,7 +514,6 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/client_channel/resolver.c ) s.files += %w( src/core/ext/client_channel/resolver.c )
s.files += %w( src/core/ext/client_channel/resolver_factory.c ) s.files += %w( src/core/ext/client_channel/resolver_factory.c )
s.files += %w( src/core/ext/client_channel/resolver_registry.c ) s.files += %w( src/core/ext/client_channel/resolver_registry.c )
s.files += %w( src/core/ext/client_channel/resolver_result.c )
s.files += %w( src/core/ext/client_channel/subchannel.c ) s.files += %w( src/core/ext/client_channel/subchannel.c )
s.files += %w( src/core/ext/client_channel/subchannel_index.c ) s.files += %w( src/core/ext/client_channel/subchannel_index.c )
s.files += %w( src/core/ext/client_channel/uri_parser.c ) s.files += %w( src/core/ext/client_channel/uri_parser.c )

@ -204,6 +204,13 @@ typedef struct {
/** Service config data, to be passed to subchannels. /** Service config data, to be passed to subchannels.
Not intended for external use. */ Not intended for external use. */
#define GRPC_ARG_SERVICE_CONFIG "grpc.service_config" #define GRPC_ARG_SERVICE_CONFIG "grpc.service_config"
/** LB policy name. */
#define GRPC_ARG_LB_POLICY_NAME "grpc.lb_policy_name"
/** Server name. Not intended for external use. */
#define GRPC_ARG_SERVER_NAME "grpc.server_name"
/** Resolved addresses in a form used by the LB policy.
Not intended for external use. */
#define GRPC_ARG_LB_ADDRESSES "grpc.lb_addresses"
/** \} */ /** \} */
/** Result of a grpc call. If the caller satisfies the prerequisites of a /** Result of a grpc call. If the caller satisfies the prerequisites of a

@ -325,7 +325,6 @@
<file baseinstalldir="/" name="src/core/ext/client_channel/resolver.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/client_channel/resolver.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/resolver_factory.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/client_channel/resolver_factory.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/resolver_registry.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/client_channel/resolver_registry.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/resolver_result.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/subchannel.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/client_channel/subchannel.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/subchannel_index.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/client_channel/subchannel_index.h" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/uri_parser.h" role="src" /> <file baseinstalldir="/" name="src/core/ext/client_channel/uri_parser.h" role="src" />
@ -522,7 +521,6 @@
<file baseinstalldir="/" name="src/core/ext/client_channel/resolver.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/client_channel/resolver.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/resolver_factory.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/client_channel/resolver_factory.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/resolver_registry.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/client_channel/resolver_registry.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/resolver_result.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/subchannel.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/client_channel/subchannel.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/subchannel_index.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/client_channel/subchannel_index.c" role="src" />
<file baseinstalldir="/" name="src/core/ext/client_channel/uri_parser.c" role="src" /> <file baseinstalldir="/" name="src/core/ext/client_channel/uri_parser.c" role="src" />

@ -5,28 +5,27 @@ This library provides high level configuration machinery to construct client
channels and load balance between them. channels and load balance between them.
Each grpc_channel is created with a grpc_resolver. It is the resolver's duty Each grpc_channel is created with a grpc_resolver. It is the resolver's duty
to resolve a name into configuration data for the channel. Such configuration to resolve a name into a set of arguments for the channel. Such arguments
data might include: might include:
- a list of (ip, port) addresses to connect to - a list of (ip, port) addresses to connect to
- a load balancing policy to decide which server to send a request to - a load balancing policy to decide which server to send a request to
- a set of filters to mutate outgoing requests (say, by adding metadata) - a set of filters to mutate outgoing requests (say, by adding metadata)
The resolver provides this data as a stream of grpc_resolver_result objects to The resolver provides this data as a stream of grpc_channel_args objects to
the channel. We represent configuration as a stream so that it can be changed the channel. We represent arguments as a stream so that they can be changed
by the resolver during execution, by reacting to external events (such as a by the resolver during execution, by reacting to external events (such as
new configuration file being pushed to some store). new service configuration data being pushed to some store).
Load Balancing Load Balancing
-------------- --------------
Load balancing configuration is provided by a grpc_lb_policy object, stored as Load balancing configuration is provided by a grpc_lb_policy object.
part of grpc_resolver_result.
The primary job of the load balancing policies is to pick a target server given only the The primary job of the load balancing policies is to pick a target server
initial metadata for a request. It does this by providing a grpc_subchannel given only the initial metadata for a request. It does this by providing
object to the owning channel. a grpc_subchannel object to the owning channel.
Sub-Channels Sub-Channels

@ -127,7 +127,7 @@ typedef struct client_channel_channel_data {
/** maps method names to method_parameters structs */ /** maps method names to method_parameters structs */
grpc_mdstr_hash_table *method_params_table; grpc_mdstr_hash_table *method_params_table;
/** incoming resolver result - set by resolver.next() */ /** incoming resolver result - set by resolver.next() */
grpc_resolver_result *resolver_result; grpc_channel_args *resolver_result;
/** a list of closures that are all waiting for config to come in */ /** a list of closures that are all waiting for config to come in */
grpc_closure_list waiting_for_config_closures; grpc_closure_list waiting_for_config_closures;
/** resolver callback */ /** resolver callback */
@ -232,35 +232,42 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
if (chand->resolver_result != NULL) { if (chand->resolver_result != NULL) {
grpc_lb_policy_args lb_policy_args; grpc_lb_policy_args lb_policy_args;
lb_policy_args.server_name = lb_policy_args.args = chand->resolver_result;
grpc_resolver_result_get_server_name(chand->resolver_result);
lb_policy_args.addresses =
grpc_resolver_result_get_addresses(chand->resolver_result);
lb_policy_args.additional_args =
grpc_resolver_result_get_lb_policy_args(chand->resolver_result);
lb_policy_args.client_channel_factory = chand->client_channel_factory; lb_policy_args.client_channel_factory = chand->client_channel_factory;
// Find LB policy name.
const char *lb_policy_name = NULL;
const grpc_arg *channel_arg =
grpc_channel_args_find(lb_policy_args.args, GRPC_ARG_LB_POLICY_NAME);
if (channel_arg != NULL) {
GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
lb_policy_name = channel_arg->value.string;
}
// Special case: If all of the addresses are balancer addresses, // Special case: If all of the addresses are balancer addresses,
// assume that we should use the grpclb policy, regardless of what the // assume that we should use the grpclb policy, regardless of what the
// resolver actually specified. // resolver actually specified.
const char *lb_policy_name = channel_arg =
grpc_resolver_result_get_lb_policy_name(chand->resolver_result); grpc_channel_args_find(lb_policy_args.args, GRPC_ARG_LB_ADDRESSES);
bool found_backend_address = false; if (channel_arg != NULL) {
for (size_t i = 0; i < lb_policy_args.addresses->num_addresses; ++i) { GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER);
if (!lb_policy_args.addresses->addresses[i].is_balancer) { grpc_lb_addresses *addresses = channel_arg->value.pointer.p;
found_backend_address = true; bool found_backend_address = false;
break; for (size_t i = 0; i < addresses->num_addresses; ++i) {
if (!addresses->addresses[i].is_balancer) {
found_backend_address = true;
break;
}
} }
} if (!found_backend_address) {
if (!found_backend_address) { if (lb_policy_name != NULL && strcmp(lb_policy_name, "grpclb") != 0) {
if (lb_policy_name != NULL && strcmp(lb_policy_name, "grpclb") != 0) { gpr_log(GPR_INFO,
gpr_log(GPR_INFO, "resolver requested LB policy %s but provided only balancer "
"resolver requested LB policy %s but provided only balancer " "addresses, no backend addresses -- forcing use of grpclb LB "
"addresses, no backend addresses -- forcing use of grpclb LB " "policy",
"policy", lb_policy_name);
(lb_policy_name == NULL ? "(none)" : lb_policy_name)); }
lb_policy_name = "grpclb";
} }
lb_policy_name = "grpclb";
} }
// Use pick_first if nothing was specified and we didn't select grpclb // Use pick_first if nothing was specified and we didn't select grpclb
// above. // above.
@ -274,15 +281,15 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
state = state =
grpc_lb_policy_check_connectivity(exec_ctx, lb_policy, &state_error); grpc_lb_policy_check_connectivity(exec_ctx, lb_policy, &state_error);
} }
const grpc_arg *channel_arg = grpc_channel_args_find( channel_arg =
lb_policy_args.additional_args, GRPC_ARG_SERVICE_CONFIG); grpc_channel_args_find(lb_policy_args.args, GRPC_ARG_SERVICE_CONFIG);
if (channel_arg != NULL) { if (channel_arg != NULL) {
GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER); GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER);
method_params_table = grpc_method_config_table_convert( method_params_table = grpc_method_config_table_convert(
(grpc_method_config_table *)channel_arg->value.pointer.p, (grpc_method_config_table *)channel_arg->value.pointer.p,
method_config_convert_value, &method_parameters_vtable); method_config_convert_value, &method_parameters_vtable);
} }
grpc_resolver_result_unref(exec_ctx, chand->resolver_result); grpc_channel_args_destroy(chand->resolver_result);
chand->resolver_result = NULL; chand->resolver_result = NULL;
} }

@ -44,14 +44,14 @@ void grpc_client_channel_factory_unref(grpc_exec_ctx* exec_ctx,
grpc_subchannel* grpc_client_channel_factory_create_subchannel( grpc_subchannel* grpc_client_channel_factory_create_subchannel(
grpc_exec_ctx* exec_ctx, grpc_client_channel_factory* factory, grpc_exec_ctx* exec_ctx, grpc_client_channel_factory* factory,
grpc_subchannel_args* args) { const grpc_subchannel_args* args) {
return factory->vtable->create_subchannel(exec_ctx, factory, args); return factory->vtable->create_subchannel(exec_ctx, factory, args);
} }
grpc_channel* grpc_client_channel_factory_create_channel( grpc_channel* grpc_client_channel_factory_create_channel(
grpc_exec_ctx* exec_ctx, grpc_client_channel_factory* factory, grpc_exec_ctx* exec_ctx, grpc_client_channel_factory* factory,
const char* target, grpc_client_channel_type type, const char* target, grpc_client_channel_type type,
grpc_channel_args* args) { const grpc_channel_args* args) {
return factory->vtable->create_client_channel(exec_ctx, factory, target, type, return factory->vtable->create_client_channel(exec_ctx, factory, target, type,
args); args);
} }

@ -60,12 +60,12 @@ struct grpc_client_channel_factory_vtable {
void (*unref)(grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory); void (*unref)(grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory);
grpc_subchannel *(*create_subchannel)(grpc_exec_ctx *exec_ctx, grpc_subchannel *(*create_subchannel)(grpc_exec_ctx *exec_ctx,
grpc_client_channel_factory *factory, grpc_client_channel_factory *factory,
grpc_subchannel_args *args); const grpc_subchannel_args *args);
grpc_channel *(*create_client_channel)(grpc_exec_ctx *exec_ctx, grpc_channel *(*create_client_channel)(grpc_exec_ctx *exec_ctx,
grpc_client_channel_factory *factory, grpc_client_channel_factory *factory,
const char *target, const char *target,
grpc_client_channel_type type, grpc_client_channel_type type,
grpc_channel_args *args); const grpc_channel_args *args);
}; };
void grpc_client_channel_factory_ref(grpc_client_channel_factory *factory); void grpc_client_channel_factory_ref(grpc_client_channel_factory *factory);
@ -75,11 +75,12 @@ void grpc_client_channel_factory_unref(grpc_exec_ctx *exec_ctx,
/** Create a new grpc_subchannel */ /** Create a new grpc_subchannel */
grpc_subchannel *grpc_client_channel_factory_create_subchannel( grpc_subchannel *grpc_client_channel_factory_create_subchannel(
grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory, grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory,
grpc_subchannel_args *args); const grpc_subchannel_args *args);
/** Create a new grpc_channel */ /** Create a new grpc_channel */
grpc_channel *grpc_client_channel_factory_create_channel( grpc_channel *grpc_client_channel_factory_create_channel(
grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory, grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory,
const char *target, grpc_client_channel_type type, grpc_channel_args *args); const char *target, grpc_client_channel_type type,
const grpc_channel_args *args);
#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_CLIENT_CHANNEL_FACTORY_H */ #endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_CLIENT_CHANNEL_FACTORY_H */

@ -38,19 +38,20 @@
#include "src/core/ext/client_channel/lb_policy_factory.h" #include "src/core/ext/client_channel/lb_policy_factory.h"
grpc_lb_addresses* grpc_lb_addresses_create(size_t num_addresses) { grpc_lb_addresses* grpc_lb_addresses_create(
size_t num_addresses, const grpc_lb_user_data_vtable* user_data_vtable) {
grpc_lb_addresses* addresses = gpr_malloc(sizeof(grpc_lb_addresses)); grpc_lb_addresses* addresses = gpr_malloc(sizeof(grpc_lb_addresses));
addresses->num_addresses = num_addresses; addresses->num_addresses = num_addresses;
addresses->user_data_vtable = user_data_vtable;
const size_t addresses_size = sizeof(grpc_lb_address) * num_addresses; const size_t addresses_size = sizeof(grpc_lb_address) * num_addresses;
addresses->addresses = gpr_malloc(addresses_size); addresses->addresses = gpr_malloc(addresses_size);
memset(addresses->addresses, 0, addresses_size); memset(addresses->addresses, 0, addresses_size);
return addresses; return addresses;
} }
grpc_lb_addresses* grpc_lb_addresses_copy(grpc_lb_addresses* addresses, grpc_lb_addresses* grpc_lb_addresses_copy(const grpc_lb_addresses* addresses) {
void* (*user_data_copy)(void*)) { grpc_lb_addresses* new_addresses = grpc_lb_addresses_create(
grpc_lb_addresses* new_addresses = addresses->num_addresses, addresses->user_data_vtable);
grpc_lb_addresses_create(addresses->num_addresses);
memcpy(new_addresses->addresses, addresses->addresses, memcpy(new_addresses->addresses, addresses->addresses,
sizeof(grpc_lb_address) * addresses->num_addresses); sizeof(grpc_lb_address) * addresses->num_addresses);
for (size_t i = 0; i < addresses->num_addresses; ++i) { for (size_t i = 0; i < addresses->num_addresses; ++i) {
@ -58,9 +59,9 @@ grpc_lb_addresses* grpc_lb_addresses_copy(grpc_lb_addresses* addresses,
new_addresses->addresses[i].balancer_name = new_addresses->addresses[i].balancer_name =
gpr_strdup(new_addresses->addresses[i].balancer_name); gpr_strdup(new_addresses->addresses[i].balancer_name);
} }
if (user_data_copy != NULL) { if (new_addresses->addresses[i].user_data != NULL) {
new_addresses->addresses[i].user_data = new_addresses->addresses[i].user_data = addresses->user_data_vtable->copy(
user_data_copy(new_addresses->addresses[i].user_data); new_addresses->addresses[i].user_data);
} }
} }
return new_addresses; return new_addresses;
@ -71,6 +72,7 @@ void grpc_lb_addresses_set_address(grpc_lb_addresses* addresses, size_t index,
bool is_balancer, char* balancer_name, bool is_balancer, char* balancer_name,
void* user_data) { void* user_data) {
GPR_ASSERT(index < addresses->num_addresses); GPR_ASSERT(index < addresses->num_addresses);
if (user_data != NULL) GPR_ASSERT(addresses->user_data_vtable != NULL);
grpc_lb_address* target = &addresses->addresses[index]; grpc_lb_address* target = &addresses->addresses[index];
memcpy(target->address.addr, address, address_len); memcpy(target->address.addr, address, address_len);
target->address.len = address_len; target->address.len = address_len;
@ -79,18 +81,70 @@ void grpc_lb_addresses_set_address(grpc_lb_addresses* addresses, size_t index,
target->user_data = user_data; target->user_data = user_data;
} }
void grpc_lb_addresses_destroy(grpc_lb_addresses* addresses, int grpc_lb_addresses_cmp(const grpc_lb_addresses* addresses1,
void (*user_data_destroy)(void*)) { const grpc_lb_addresses* addresses2) {
if (addresses1->num_addresses > addresses2->num_addresses) return 1;
if (addresses1->num_addresses < addresses2->num_addresses) return -1;
if (addresses1->user_data_vtable > addresses2->user_data_vtable) return 1;
if (addresses1->user_data_vtable < addresses2->user_data_vtable) return -1;
for (size_t i = 0; i < addresses1->num_addresses; ++i) {
const grpc_lb_address* target1 = &addresses1->addresses[i];
const grpc_lb_address* target2 = &addresses2->addresses[i];
if (target1->address.len > target2->address.len) return 1;
if (target1->address.len < target2->address.len) return -1;
int retval = memcmp(target1->address.addr, target2->address.addr,
target1->address.len);
if (retval != 0) return retval;
if (target1->is_balancer > target2->is_balancer) return 1;
if (target1->is_balancer < target2->is_balancer) return -1;
const char* balancer_name1 =
target1->balancer_name != NULL ? target1->balancer_name : "";
const char* balancer_name2 =
target2->balancer_name != NULL ? target2->balancer_name : "";
retval = strcmp(balancer_name1, balancer_name2);
if (retval != 0) return retval;
if (addresses1->user_data_vtable != NULL) {
retval = addresses1->user_data_vtable->cmp(target1->user_data,
target2->user_data);
if (retval != 0) return retval;
}
}
return 0;
}
void grpc_lb_addresses_destroy(grpc_lb_addresses* addresses) {
for (size_t i = 0; i < addresses->num_addresses; ++i) { for (size_t i = 0; i < addresses->num_addresses; ++i) {
gpr_free(addresses->addresses[i].balancer_name); gpr_free(addresses->addresses[i].balancer_name);
if (user_data_destroy != NULL) { if (addresses->addresses[i].user_data != NULL) {
user_data_destroy(addresses->addresses[i].user_data); addresses->user_data_vtable->destroy(addresses->addresses[i].user_data);
} }
} }
gpr_free(addresses->addresses); gpr_free(addresses->addresses);
gpr_free(addresses); gpr_free(addresses);
} }
static void* lb_addresses_copy(void* addresses) {
return grpc_lb_addresses_copy(addresses);
}
static void lb_addresses_destroy(void* addresses) {
grpc_lb_addresses_destroy(addresses);
}
static int lb_addresses_cmp(void* addresses1, void* addresses2) {
return grpc_lb_addresses_cmp(addresses1, addresses2);
}
static const grpc_arg_pointer_vtable lb_addresses_arg_vtable = {
lb_addresses_copy, lb_addresses_destroy, lb_addresses_cmp};
grpc_arg grpc_lb_addresses_create_channel_arg(
const grpc_lb_addresses* addresses) {
grpc_arg arg;
arg.type = GRPC_ARG_POINTER;
arg.key = GRPC_ARG_LB_ADDRESSES;
arg.value.pointer.p = (void*)addresses;
arg.value.pointer.vtable = &lb_addresses_arg_vtable;
return arg;
}
void grpc_lb_policy_factory_ref(grpc_lb_policy_factory* factory) { void grpc_lb_policy_factory_ref(grpc_lb_policy_factory* factory) {
factory->vtable->ref(factory); factory->vtable->ref(factory);
} }

@ -59,19 +59,26 @@ typedef struct grpc_lb_address {
void *user_data; void *user_data;
} grpc_lb_address; } grpc_lb_address;
typedef struct grpc_lb_user_data_vtable {
void *(*copy)(void *);
void (*destroy)(void *);
int (*cmp)(void *, void *);
} grpc_lb_user_data_vtable;
typedef struct grpc_lb_addresses { typedef struct grpc_lb_addresses {
size_t num_addresses; size_t num_addresses;
grpc_lb_address *addresses; grpc_lb_address *addresses;
const grpc_lb_user_data_vtable *user_data_vtable;
} grpc_lb_addresses; } grpc_lb_addresses;
/** Returns a grpc_addresses struct with enough space for /** Returns a grpc_addresses struct with enough space for
* \a num_addresses addresses. */ \a num_addresses addresses. The \a user_data_vtable argument may be
grpc_lb_addresses *grpc_lb_addresses_create(size_t num_addresses); NULL if no user data will be added. */
grpc_lb_addresses *grpc_lb_addresses_create(
size_t num_addresses, const grpc_lb_user_data_vtable *user_data_vtable);
/** Creates a copy of \a addresses. If \a user_data_copy is not NULL, /** Creates a copy of \a addresses. */
* it will be invoked to copy the \a user_data field of each address. */ grpc_lb_addresses *grpc_lb_addresses_copy(const grpc_lb_addresses *addresses);
grpc_lb_addresses *grpc_lb_addresses_copy(grpc_lb_addresses *addresses,
void *(*user_data_copy)(void *));
/** Sets the value of the address at index \a index of \a addresses. /** Sets the value of the address at index \a index of \a addresses.
* \a address is a socket address of length \a address_len. * \a address is a socket address of length \a address_len.
@ -81,20 +88,21 @@ void grpc_lb_addresses_set_address(grpc_lb_addresses *addresses, size_t index,
bool is_balancer, char *balancer_name, bool is_balancer, char *balancer_name,
void *user_data); void *user_data);
/** Destroys \a addresses. If \a user_data_destroy is not NULL, it will /** Compares \a addresses1 and \a addresses2. */
* be invoked to destroy the \a user_data field of each address. */ int grpc_lb_addresses_cmp(const grpc_lb_addresses *addresses1,
void grpc_lb_addresses_destroy(grpc_lb_addresses *addresses, const grpc_lb_addresses *addresses2);
void (*user_data_destroy)(void *));
/** Destroys \a addresses. */
void grpc_lb_addresses_destroy(grpc_lb_addresses *addresses);
/** Returns a channel arg containing \a addresses. */
grpc_arg grpc_lb_addresses_create_channel_arg(
const grpc_lb_addresses *addresses);
/** Arguments passed to LB policies. */ /** Arguments passed to LB policies. */
/* TODO(roth, ctiller): Consider replacing this struct with
grpc_channel_args. See comment in resolver_result.h for details. */
typedef struct grpc_lb_policy_args { typedef struct grpc_lb_policy_args {
const char *server_name;
grpc_lb_addresses *addresses;
grpc_client_channel_factory *client_channel_factory; grpc_client_channel_factory *client_channel_factory;
/* Can be used to pass implementation-specific parameters to the LB policy. */ grpc_channel_args *args;
grpc_channel_args *additional_args;
} grpc_lb_policy_args; } grpc_lb_policy_args;
struct grpc_lb_policy_factory_vtable { struct grpc_lb_policy_factory_vtable {

@ -76,7 +76,6 @@ void grpc_resolver_channel_saw_error(grpc_exec_ctx *exec_ctx,
} }
void grpc_resolver_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver, void grpc_resolver_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
grpc_resolver_result **result, grpc_channel_args **result, grpc_closure *on_complete) {
grpc_closure *on_complete) {
resolver->vtable->next(exec_ctx, resolver, result, on_complete); resolver->vtable->next(exec_ctx, resolver, result, on_complete);
} }

@ -34,15 +34,13 @@
#ifndef GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_H #ifndef GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_H
#define GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_H #define GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_H
#include "src/core/ext/client_channel/resolver_result.h"
#include "src/core/ext/client_channel/subchannel.h" #include "src/core/ext/client_channel/subchannel.h"
#include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/iomgr.h"
typedef struct grpc_resolver grpc_resolver; typedef struct grpc_resolver grpc_resolver;
typedef struct grpc_resolver_vtable grpc_resolver_vtable; typedef struct grpc_resolver_vtable grpc_resolver_vtable;
/** grpc_resolver provides grpc_resolver_result objects to grpc_channel /** \a grpc_resolver provides \a grpc_channel_args objects to its caller */
objects */
struct grpc_resolver { struct grpc_resolver {
const grpc_resolver_vtable *vtable; const grpc_resolver_vtable *vtable;
gpr_refcount refs; gpr_refcount refs;
@ -53,7 +51,7 @@ struct grpc_resolver_vtable {
void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver); void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
void (*channel_saw_error)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver); void (*channel_saw_error)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
void (*next)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver, void (*next)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
grpc_resolver_result **result, grpc_closure *on_complete); grpc_channel_args **result, grpc_closure *on_complete);
}; };
#ifdef GRPC_RESOLVER_REFCOUNT_DEBUG #ifdef GRPC_RESOLVER_REFCOUNT_DEBUG
@ -81,14 +79,12 @@ void grpc_resolver_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
void grpc_resolver_channel_saw_error(grpc_exec_ctx *exec_ctx, void grpc_resolver_channel_saw_error(grpc_exec_ctx *exec_ctx,
grpc_resolver *resolver); grpc_resolver *resolver);
/** Get the next client config. Called by the channel to fetch a new /** Get the next result from the resolver. Expected to set \a *result with
configuration. Expected to set *result with a new configuration, new channel args and then schedule \a on_complete for execution.
and then schedule on_complete for execution.
If resolution is fatally broken, set *result to NULL and If resolution is fatally broken, set \a *result to NULL and
schedule on_complete. */ schedule \a on_complete. */
void grpc_resolver_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver, void grpc_resolver_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
grpc_resolver_result **result, grpc_channel_args **result, grpc_closure *on_complete);
grpc_closure *on_complete);
#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_H */ #endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_H */

@ -41,13 +41,14 @@
typedef struct grpc_resolver_factory grpc_resolver_factory; typedef struct grpc_resolver_factory grpc_resolver_factory;
typedef struct grpc_resolver_factory_vtable grpc_resolver_factory_vtable; typedef struct grpc_resolver_factory_vtable grpc_resolver_factory_vtable;
/** grpc_resolver provides grpc_resolver_result objects to grpc_channel
objects */
struct grpc_resolver_factory { struct grpc_resolver_factory {
const grpc_resolver_factory_vtable *vtable; const grpc_resolver_factory_vtable *vtable;
}; };
typedef struct grpc_resolver_args { grpc_uri *uri; } grpc_resolver_args; typedef struct grpc_resolver_args {
grpc_uri *uri;
const grpc_channel_args *args;
} grpc_resolver_args;
struct grpc_resolver_factory_vtable { struct grpc_resolver_factory_vtable {
void (*ref)(grpc_resolver_factory *factory); void (*ref)(grpc_resolver_factory *factory);

@ -131,14 +131,16 @@ static grpc_resolver_factory *resolve_factory(const char *target,
return factory; return factory;
} }
grpc_resolver *grpc_resolver_create(const char *target) { grpc_resolver *grpc_resolver_create(const char *target,
const grpc_channel_args *args) {
grpc_uri *uri = NULL; grpc_uri *uri = NULL;
grpc_resolver_factory *factory = resolve_factory(target, &uri); grpc_resolver_factory *factory = resolve_factory(target, &uri);
grpc_resolver *resolver; grpc_resolver *resolver;
grpc_resolver_args args; grpc_resolver_args resolver_args;
memset(&args, 0, sizeof(args)); memset(&resolver_args, 0, sizeof(resolver_args));
args.uri = uri; resolver_args.uri = uri;
resolver = grpc_resolver_factory_create_resolver(factory, &args); resolver_args.args = args;
resolver = grpc_resolver_factory_create_resolver(factory, &resolver_args);
grpc_uri_destroy(uri); grpc_uri_destroy(uri);
return resolver; return resolver;
} }

@ -57,8 +57,11 @@ void grpc_register_resolver_type(grpc_resolver_factory *factory);
was not NULL). was not NULL).
If a resolver factory was found, use it to instantiate a resolver and If a resolver factory was found, use it to instantiate a resolver and
return it. return it.
If a resolver factory was not found, return NULL. */ If a resolver factory was not found, return NULL.
grpc_resolver *grpc_resolver_create(const char *target); \a args is a set of channel arguments to be included in the result
(typically the set of arguments passed in from the client API). */
grpc_resolver *grpc_resolver_create(const char *target,
const grpc_channel_args *args);
/** Find a resolver factory given a name and return an (owned-by-the-caller) /** Find a resolver factory given a name and return an (owned-by-the-caller)
* reference to it */ * reference to it */

@ -1,94 +0,0 @@
//
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#include "src/core/ext/client_channel/resolver_result.h"
#include <string.h>
#include <grpc/support/alloc.h>
#include <grpc/support/string_util.h>
#include "src/core/lib/channel/channel_args.h"
struct grpc_resolver_result {
gpr_refcount refs;
char* server_name;
grpc_lb_addresses* addresses;
char* lb_policy_name;
grpc_channel_args* lb_policy_args;
};
grpc_resolver_result* grpc_resolver_result_create(
const char* server_name, grpc_lb_addresses* addresses,
const char* lb_policy_name, grpc_channel_args* lb_policy_args) {
grpc_resolver_result* result = gpr_malloc(sizeof(*result));
memset(result, 0, sizeof(*result));
gpr_ref_init(&result->refs, 1);
result->server_name = gpr_strdup(server_name);
result->addresses = addresses;
result->lb_policy_name = gpr_strdup(lb_policy_name);
result->lb_policy_args = lb_policy_args;
return result;
}
void grpc_resolver_result_ref(grpc_resolver_result* result) {
gpr_ref(&result->refs);
}
void grpc_resolver_result_unref(grpc_exec_ctx* exec_ctx,
grpc_resolver_result* result) {
if (gpr_unref(&result->refs)) {
gpr_free(result->server_name);
grpc_lb_addresses_destroy(result->addresses, NULL /* user_data_destroy */);
gpr_free(result->lb_policy_name);
grpc_channel_args_destroy(result->lb_policy_args);
gpr_free(result);
}
}
const char* grpc_resolver_result_get_server_name(grpc_resolver_result* result) {
return result->server_name;
}
grpc_lb_addresses* grpc_resolver_result_get_addresses(
grpc_resolver_result* result) {
return result->addresses;
}
const char* grpc_resolver_result_get_lb_policy_name(
grpc_resolver_result* result) {
return result->lb_policy_name;
}
grpc_channel_args* grpc_resolver_result_get_lb_policy_args(
grpc_resolver_result* result) {
return result->lb_policy_args;
}

@ -1,68 +0,0 @@
//
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#ifndef GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_RESULT_H
#define GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_RESULT_H
#include "src/core/ext/client_channel/lb_policy_factory.h"
// TODO(roth, ctiller): In the long term, we are considering replacing
// the resolver_result data structure with grpc_channel_args. The idea is
// that the resolver will return a set of channel args that contains the
// information that is currently in the resolver_result struct. For
// example, there will be specific args indicating the set of addresses
// and the name of the LB policy to instantiate. Note that if we did
// this, we would probably want to change the data structure of
// grpc_channel_args such to a hash table or AVL or some other data
// structure that does not require linear search to find keys.
/// Results reported from a grpc_resolver.
typedef struct grpc_resolver_result grpc_resolver_result;
/// Takes ownership of \a addresses and \a lb_policy_args.
grpc_resolver_result* grpc_resolver_result_create(
const char* server_name, grpc_lb_addresses* addresses,
const char* lb_policy_name, grpc_channel_args* lb_policy_args);
void grpc_resolver_result_ref(grpc_resolver_result* result);
void grpc_resolver_result_unref(grpc_exec_ctx* exec_ctx,
grpc_resolver_result* result);
/// Accessors. Caller does NOT take ownership of results.
const char* grpc_resolver_result_get_server_name(grpc_resolver_result* result);
grpc_lb_addresses* grpc_resolver_result_get_addresses(
grpc_resolver_result* result);
const char* grpc_resolver_result_get_lb_policy_name(
grpc_resolver_result* result);
grpc_channel_args* grpc_resolver_result_get_lb_policy_args(
grpc_resolver_result* result);
#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_RESULT_H */

@ -297,7 +297,7 @@ void grpc_subchannel_weak_unref(grpc_exec_ctx *exec_ctx,
grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx, grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
grpc_connector *connector, grpc_connector *connector,
grpc_subchannel_args *args) { const grpc_subchannel_args *args) {
grpc_subchannel_key *key = grpc_subchannel_key_create(connector, args); grpc_subchannel_key *key = grpc_subchannel_key_create(connector, args);
grpc_subchannel *c = grpc_subchannel_index_find(exec_ctx, key); grpc_subchannel *c = grpc_subchannel_index_find(exec_ctx, key);
if (c) { if (c) {

@ -173,6 +173,6 @@ struct grpc_subchannel_args {
/** create a subchannel given a connector */ /** create a subchannel given a connector */
grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx, grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
grpc_connector *connector, grpc_connector *connector,
grpc_subchannel_args *args); const grpc_subchannel_args *args);
#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_SUBCHANNEL_H */ #endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_SUBCHANNEL_H */

@ -73,7 +73,7 @@ static grpc_exec_ctx *current_ctx() {
} }
static grpc_subchannel_key *create_key( static grpc_subchannel_key *create_key(
grpc_connector *connector, grpc_subchannel_args *args, grpc_connector *connector, const grpc_subchannel_args *args,
grpc_channel_args *(*copy_channel_args)(const grpc_channel_args *args)) { grpc_channel_args *(*copy_channel_args)(const grpc_channel_args *args)) {
grpc_subchannel_key *k = gpr_malloc(sizeof(*k)); grpc_subchannel_key *k = gpr_malloc(sizeof(*k));
k->connector = grpc_connector_ref(connector); k->connector = grpc_connector_ref(connector);
@ -96,8 +96,8 @@ static grpc_subchannel_key *create_key(
return k; return k;
} }
grpc_subchannel_key *grpc_subchannel_key_create(grpc_connector *connector, grpc_subchannel_key *grpc_subchannel_key_create(
grpc_subchannel_args *args) { grpc_connector *connector, const grpc_subchannel_args *args) {
return create_key(connector, args, grpc_channel_args_normalize); return create_key(connector, args, grpc_channel_args_normalize);
} }

@ -43,8 +43,8 @@
typedef struct grpc_subchannel_key grpc_subchannel_key; typedef struct grpc_subchannel_key grpc_subchannel_key;
/** Create a key that can be used to uniquely identify a subchannel */ /** Create a key that can be used to uniquely identify a subchannel */
grpc_subchannel_key *grpc_subchannel_key_create(grpc_connector *con, grpc_subchannel_key *grpc_subchannel_key_create(
grpc_subchannel_args *args); grpc_connector *con, const grpc_subchannel_args *args);
/** Destroy a subchannel key */ /** Destroy a subchannel key */
void grpc_subchannel_key_destroy(grpc_exec_ctx *exec_ctx, void grpc_subchannel_key_destroy(grpc_exec_ctx *exec_ctx,

@ -343,6 +343,21 @@ static bool is_server_valid(const grpc_grpclb_server *server, size_t idx,
return true; return true;
} }
/* vtable for LB tokens in grpc_lb_addresses. */
static void *lb_token_copy(void *token) {
return token == NULL ? NULL : GRPC_MDELEM_REF(token);
}
static void lb_token_destroy(void *token) {
if (token != NULL) GRPC_MDELEM_UNREF(token);
}
static int lb_token_cmp(void *token1, void *token2) {
if (token1 > token2) return 1;
if (token1 < token2) return -1;
return 0;
}
static const grpc_lb_user_data_vtable lb_token_vtable = {
lb_token_copy, lb_token_destroy, lb_token_cmp};
/* Returns addresses extracted from \a serverlist. */ /* Returns addresses extracted from \a serverlist. */
static grpc_lb_addresses *process_serverlist( static grpc_lb_addresses *process_serverlist(
const grpc_grpclb_serverlist *serverlist) { const grpc_grpclb_serverlist *serverlist) {
@ -354,7 +369,8 @@ static grpc_lb_addresses *process_serverlist(
} }
if (num_valid == 0) return NULL; if (num_valid == 0) return NULL;
grpc_lb_addresses *lb_addresses = grpc_lb_addresses_create(num_valid); grpc_lb_addresses *lb_addresses =
grpc_lb_addresses_create(num_valid, &lb_token_vtable);
/* second pass: actually populate the addresses and LB tokens (aka user data /* second pass: actually populate the addresses and LB tokens (aka user data
* to the outside world) to be read by the RR policy during its creation. * to the outside world) to be read by the RR policy during its creation.
@ -415,11 +431,6 @@ static grpc_lb_addresses *process_serverlist(
return lb_addresses; return lb_addresses;
} }
/* A plugin for grpc_lb_addresses_destroy that unrefs the LB token metadata. */
static void lb_token_destroy(void *token) {
if (token != NULL) GRPC_MDELEM_UNREF(token);
}
/* perform a pick over \a rr_policy. Given that a pick can return immediately /* perform a pick over \a rr_policy. Given that a pick can return immediately
* (ignoring its completion callback) we need to perform the cleanups this * (ignoring its completion callback) we need to perform the cleanups this
* callback would be otherwise resposible for */ * callback would be otherwise resposible for */
@ -459,20 +470,27 @@ static grpc_lb_policy *create_rr_locked(
glb_lb_policy *glb_policy) { glb_lb_policy *glb_policy) {
GPR_ASSERT(serverlist != NULL && serverlist->num_servers > 0); GPR_ASSERT(serverlist != NULL && serverlist->num_servers > 0);
if (glb_policy->addresses != NULL) {
/* dispose of the previous version */
grpc_lb_addresses_destroy(glb_policy->addresses);
}
glb_policy->addresses = process_serverlist(serverlist);
grpc_lb_policy_args args; grpc_lb_policy_args args;
memset(&args, 0, sizeof(args)); memset(&args, 0, sizeof(args));
args.server_name = glb_policy->server_name;
args.client_channel_factory = glb_policy->cc_factory; args.client_channel_factory = glb_policy->cc_factory;
args.addresses = process_serverlist(serverlist);
args.additional_args = glb_policy->args;
grpc_lb_policy *rr = grpc_lb_policy_create(exec_ctx, "round_robin", &args); // Replace the LB addresses in the channel args that we pass down to
// the subchannel.
static const char *keys_to_remove[] = {GRPC_ARG_LB_ADDRESSES};
const grpc_arg arg =
grpc_lb_addresses_create_channel_arg(glb_policy->addresses);
args.args = grpc_channel_args_copy_and_add_and_remove(
glb_policy->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &arg,
1);
if (glb_policy->addresses != NULL) { grpc_lb_policy *rr = grpc_lb_policy_create(exec_ctx, "round_robin", &args);
/* dispose of the previous version */ grpc_channel_args_destroy(args.args);
grpc_lb_addresses_destroy(glb_policy->addresses, lb_token_destroy);
}
glb_policy->addresses = args.addresses;
return rr; return rr;
} }
@ -568,6 +586,12 @@ static void glb_rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx, static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
grpc_lb_policy_factory *factory, grpc_lb_policy_factory *factory,
grpc_lb_policy_args *args) { grpc_lb_policy_args *args) {
/* Get server name. */
const grpc_arg *arg =
grpc_channel_args_find(args->args, GRPC_ARG_SERVER_NAME);
const char *server_name =
arg != NULL && arg->type == GRPC_ARG_STRING ? arg->value.string : NULL;
/* Count the number of gRPC-LB addresses. There must be at least one. /* Count the number of gRPC-LB addresses. There must be at least one.
* TODO(roth): For now, we ignore non-balancer addresses, but in the * TODO(roth): For now, we ignore non-balancer addresses, but in the
* future, we may change the behavior such that we fall back to using * future, we may change the behavior such that we fall back to using
@ -575,24 +599,27 @@ static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
* time, this should be changed to allow a list with no balancer addresses, * time, this should be changed to allow a list with no balancer addresses,
* since the resolver might fail to return a balancer address even when * since the resolver might fail to return a balancer address even when
* this is the right LB policy to use. */ * this is the right LB policy to use. */
arg = grpc_channel_args_find(args->args, GRPC_ARG_LB_ADDRESSES);
GPR_ASSERT(arg != NULL && arg->type == GRPC_ARG_POINTER);
grpc_lb_addresses *addresses = arg->value.pointer.p;
size_t num_grpclb_addrs = 0; size_t num_grpclb_addrs = 0;
for (size_t i = 0; i < args->addresses->num_addresses; ++i) { for (size_t i = 0; i < addresses->num_addresses; ++i) {
if (args->addresses->addresses[i].is_balancer) ++num_grpclb_addrs; if (addresses->addresses[i].is_balancer) ++num_grpclb_addrs;
} }
if (num_grpclb_addrs == 0) return NULL; if (num_grpclb_addrs == 0) return NULL;
glb_lb_policy *glb_policy = gpr_malloc(sizeof(*glb_policy)); glb_lb_policy *glb_policy = gpr_malloc(sizeof(*glb_policy));
memset(glb_policy, 0, sizeof(*glb_policy)); memset(glb_policy, 0, sizeof(*glb_policy));
/* All input addresses in args->addresses come from a resolver that claims /* All input addresses in addresses come from a resolver that claims
* they are LB services. It's the resolver's responsibility to make sure * they are LB services. It's the resolver's responsibility to make sure
* this * this
* policy is only instantiated and used in that case. * policy is only instantiated and used in that case.
* *
* Create a client channel over them to communicate with a LB service */ * Create a client channel over them to communicate with a LB service */
glb_policy->server_name = gpr_strdup(args->server_name); glb_policy->server_name = gpr_strdup(server_name);
glb_policy->cc_factory = args->client_channel_factory; glb_policy->cc_factory = args->client_channel_factory;
glb_policy->args = grpc_channel_args_copy(args->additional_args); glb_policy->args = grpc_channel_args_copy(args->args);
GPR_ASSERT(glb_policy->cc_factory != NULL); GPR_ASSERT(glb_policy->cc_factory != NULL);
/* construct a target from the addresses in args, given in the form /* construct a target from the addresses in args, given in the form
@ -600,19 +627,19 @@ static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
* TODO(dgq): support mixed ip version */ * TODO(dgq): support mixed ip version */
char **addr_strs = gpr_malloc(sizeof(char *) * num_grpclb_addrs); char **addr_strs = gpr_malloc(sizeof(char *) * num_grpclb_addrs);
size_t addr_index = 0; size_t addr_index = 0;
for (size_t i = 0; i < args->addresses->num_addresses; i++) { for (size_t i = 0; i < addresses->num_addresses; i++) {
if (args->addresses->addresses[i].user_data != NULL) { if (addresses->addresses[i].user_data != NULL) {
gpr_log(GPR_ERROR, gpr_log(GPR_ERROR,
"This LB policy doesn't support user data. It will be ignored"); "This LB policy doesn't support user data. It will be ignored");
} }
if (args->addresses->addresses[i].is_balancer) { if (addresses->addresses[i].is_balancer) {
if (addr_index == 0) { if (addr_index == 0) {
addr_strs[addr_index++] = addr_strs[addr_index++] =
grpc_sockaddr_to_uri(&args->addresses->addresses[i].address); grpc_sockaddr_to_uri(&addresses->addresses[i].address);
} else { } else {
GPR_ASSERT(grpc_sockaddr_to_string( GPR_ASSERT(grpc_sockaddr_to_string(&addr_strs[addr_index++],
&addr_strs[addr_index++], &addresses->addresses[i].address,
&args->addresses->addresses[i].address, true) > 0); true) > 0);
} }
} }
} }
@ -620,10 +647,29 @@ static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
char *target_uri_str = gpr_strjoin_sep((const char **)addr_strs, char *target_uri_str = gpr_strjoin_sep((const char **)addr_strs,
num_grpclb_addrs, ",", &uri_path_len); num_grpclb_addrs, ",", &uri_path_len);
/* will pick using pick_first */ /* Create a channel to talk to the LBs.
*
* We strip out the channel arg for the LB policy name, since we want
* to use the default (pick_first) in this case.
*
* We also strip out the channel arg for the resolved addresses, since
* that will be generated by the name resolver used in the LB channel.
* Note that the LB channel will use the sockaddr resolver, so this
* won't actually generate a query to DNS (or some other name service).
* However, the addresses returned by the sockaddr resolver will have
* is_balancer=false, whereas our own addresses have is_balancer=true.
* We need the LB channel to return addresses with is_balancer=false
* so that it does not wind up recursively using the grpclb LB policy,
* as per the special case logic in client_channel.c.
*/
static const char *keys_to_remove[] = {GRPC_ARG_LB_POLICY_NAME,
GRPC_ARG_LB_ADDRESSES};
grpc_channel_args *new_args = grpc_channel_args_copy_and_remove(
args->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove));
glb_policy->lb_channel = grpc_client_channel_factory_create_channel( glb_policy->lb_channel = grpc_client_channel_factory_create_channel(
exec_ctx, glb_policy->cc_factory, target_uri_str, exec_ctx, glb_policy->cc_factory, target_uri_str,
GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, NULL); GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, new_args);
grpc_channel_args_destroy(new_args);
gpr_free(target_uri_str); gpr_free(target_uri_str);
for (size_t i = 0; i < num_grpclb_addrs; i++) { for (size_t i = 0; i < num_grpclb_addrs; i++) {
@ -664,7 +710,7 @@ static void glb_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
grpc_grpclb_destroy_serverlist(glb_policy->serverlist); grpc_grpclb_destroy_serverlist(glb_policy->serverlist);
} }
gpr_mu_destroy(&glb_policy->mu); gpr_mu_destroy(&glb_policy->mu);
grpc_lb_addresses_destroy(glb_policy->addresses, lb_token_destroy); grpc_lb_addresses_destroy(glb_policy->addresses);
gpr_free(glb_policy); gpr_free(glb_policy);
} }

@ -34,7 +34,9 @@
#include <string.h> #include <string.h>
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include "src/core/ext/client_channel/lb_policy_registry.h" #include "src/core/ext/client_channel/lb_policy_registry.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/connectivity_state.h"
typedef struct pending_pick { typedef struct pending_pick {
@ -432,14 +434,22 @@ static void pick_first_factory_unref(grpc_lb_policy_factory *factory) {}
static grpc_lb_policy *create_pick_first(grpc_exec_ctx *exec_ctx, static grpc_lb_policy *create_pick_first(grpc_exec_ctx *exec_ctx,
grpc_lb_policy_factory *factory, grpc_lb_policy_factory *factory,
grpc_lb_policy_args *args) { grpc_lb_policy_args *args) {
GPR_ASSERT(args->addresses != NULL);
GPR_ASSERT(args->client_channel_factory != NULL); GPR_ASSERT(args->client_channel_factory != NULL);
/* Get server name. */
const grpc_arg *arg =
grpc_channel_args_find(args->args, GRPC_ARG_SERVER_NAME);
const char *server_name =
arg != NULL && arg->type == GRPC_ARG_STRING ? arg->value.string : NULL;
/* Find the number of backend addresses. We ignore balancer /* Find the number of backend addresses. We ignore balancer
* addresses, since we don't know how to handle them. */ * addresses, since we don't know how to handle them. */
arg = grpc_channel_args_find(args->args, GRPC_ARG_LB_ADDRESSES);
GPR_ASSERT(arg != NULL && arg->type == GRPC_ARG_POINTER);
grpc_lb_addresses *addresses = arg->value.pointer.p;
size_t num_addrs = 0; size_t num_addrs = 0;
for (size_t i = 0; i < args->addresses->num_addresses; i++) { for (size_t i = 0; i < addresses->num_addresses; i++) {
if (!args->addresses->addresses[i].is_balancer) ++num_addrs; if (!addresses->addresses[i].is_balancer) ++num_addrs;
} }
if (num_addrs == 0) return NULL; if (num_addrs == 0) return NULL;
@ -450,21 +460,21 @@ static grpc_lb_policy *create_pick_first(grpc_exec_ctx *exec_ctx,
memset(p->subchannels, 0, sizeof(*p->subchannels) * num_addrs); memset(p->subchannels, 0, sizeof(*p->subchannels) * num_addrs);
grpc_subchannel_args sc_args; grpc_subchannel_args sc_args;
size_t subchannel_idx = 0; size_t subchannel_idx = 0;
for (size_t i = 0; i < args->addresses->num_addresses; i++) { for (size_t i = 0; i < addresses->num_addresses; i++) {
/* Skip balancer addresses, since we only know how to handle backends. */ /* Skip balancer addresses, since we only know how to handle backends. */
if (args->addresses->addresses[i].is_balancer) continue; if (addresses->addresses[i].is_balancer) continue;
if (args->addresses->addresses[i].user_data != NULL) { if (addresses->addresses[i].user_data != NULL) {
gpr_log(GPR_ERROR, gpr_log(GPR_ERROR,
"This LB policy doesn't support user data. It will be ignored"); "This LB policy doesn't support user data. It will be ignored");
} }
memset(&sc_args, 0, sizeof(grpc_subchannel_args)); memset(&sc_args, 0, sizeof(grpc_subchannel_args));
/* server_name will be copied as part of the subchannel creation. This makes /* server_name will be copied as part of the subchannel creation. This makes
* the copying of args->server_name (a borrowed pointer) OK. */ * the copying of server_name (a borrowed pointer) OK. */
sc_args.server_name = args->server_name; sc_args.server_name = server_name;
sc_args.addr = &args->addresses->addresses[i].address; sc_args.addr = &addresses->addresses[i].address;
sc_args.args = args->additional_args; sc_args.args = args->args;
grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel( grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel(
exec_ctx, args->client_channel_factory, &sc_args); exec_ctx, args->client_channel_factory, &sc_args);

@ -64,6 +64,7 @@
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include "src/core/ext/client_channel/lb_policy_registry.h" #include "src/core/ext/client_channel/lb_policy_registry.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/debug/trace.h" #include "src/core/lib/debug/trace.h"
#include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/connectivity_state.h"
#include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/static_metadata.h"
@ -598,14 +599,22 @@ static void round_robin_factory_unref(grpc_lb_policy_factory *factory) {}
static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx, static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx,
grpc_lb_policy_factory *factory, grpc_lb_policy_factory *factory,
grpc_lb_policy_args *args) { grpc_lb_policy_args *args) {
GPR_ASSERT(args->addresses != NULL);
GPR_ASSERT(args->client_channel_factory != NULL); GPR_ASSERT(args->client_channel_factory != NULL);
/* Get server name. */
const grpc_arg *arg =
grpc_channel_args_find(args->args, GRPC_ARG_SERVER_NAME);
const char *server_name =
arg != NULL && arg->type == GRPC_ARG_STRING ? arg->value.string : NULL;
/* Find the number of backend addresses. We ignore balancer /* Find the number of backend addresses. We ignore balancer
* addresses, since we don't know how to handle them. */ * addresses, since we don't know how to handle them. */
arg = grpc_channel_args_find(args->args, GRPC_ARG_LB_ADDRESSES);
GPR_ASSERT(arg != NULL && arg->type == GRPC_ARG_POINTER);
grpc_lb_addresses *addresses = arg->value.pointer.p;
size_t num_addrs = 0; size_t num_addrs = 0;
for (size_t i = 0; i < args->addresses->num_addresses; i++) { for (size_t i = 0; i < addresses->num_addresses; i++) {
if (!args->addresses->addresses[i].is_balancer) ++num_addrs; if (!addresses->addresses[i].is_balancer) ++num_addrs;
} }
if (num_addrs == 0) return NULL; if (num_addrs == 0) return NULL;
@ -618,16 +627,16 @@ static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx,
grpc_subchannel_args sc_args; grpc_subchannel_args sc_args;
size_t subchannel_idx = 0; size_t subchannel_idx = 0;
for (size_t i = 0; i < args->addresses->num_addresses; i++) { for (size_t i = 0; i < addresses->num_addresses; i++) {
/* Skip balancer addresses, since we only know how to handle backends. */ /* Skip balancer addresses, since we only know how to handle backends. */
if (args->addresses->addresses[i].is_balancer) continue; if (addresses->addresses[i].is_balancer) continue;
memset(&sc_args, 0, sizeof(grpc_subchannel_args)); memset(&sc_args, 0, sizeof(grpc_subchannel_args));
/* server_name will be copied as part of the subchannel creation. This makes /* server_name will be copied as part of the subchannel creation. This makes
* the copying of args->server_name (a borrowed pointer) OK. */ * the copying of server_name (a borrowed pointer) OK. */
sc_args.server_name = args->server_name; sc_args.server_name = server_name;
sc_args.addr = &args->addresses->addresses[i].address; sc_args.addr = &addresses->addresses[i].address;
sc_args.args = args->additional_args; sc_args.args = args->args;
grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel( grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel(
exec_ctx, args->client_channel_factory, &sc_args); exec_ctx, args->client_channel_factory, &sc_args);
@ -639,7 +648,7 @@ static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx,
sd->policy = p; sd->policy = p;
sd->index = subchannel_idx; sd->index = subchannel_idx;
sd->subchannel = subchannel; sd->subchannel = subchannel;
sd->user_data = args->addresses->addresses[i].user_data; sd->user_data = addresses->addresses[i].user_data;
++subchannel_idx; ++subchannel_idx;
grpc_closure_init(&sd->connectivity_changed_closure, grpc_closure_init(&sd->connectivity_changed_closure,
rr_connectivity_changed, sd); rr_connectivity_changed, sd);

@ -40,6 +40,7 @@
#include "src/core/ext/client_channel/http_connect_handshaker.h" #include "src/core/ext/client_channel/http_connect_handshaker.h"
#include "src/core/ext/client_channel/lb_policy_registry.h" #include "src/core/ext/client_channel/lb_policy_registry.h"
#include "src/core/ext/client_channel/resolver_registry.h" #include "src/core/ext/client_channel/resolver_registry.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/timer.h" #include "src/core/lib/iomgr/timer.h"
#include "src/core/lib/support/backoff.h" #include "src/core/lib/support/backoff.h"
@ -53,12 +54,12 @@
typedef struct { typedef struct {
/** base class: must be first */ /** base class: must be first */
grpc_resolver base; grpc_resolver base;
/** target name */ /** name to resolve */
char *target_name;
/** name to resolve (usually the same as target_name) */
char *name_to_resolve; char *name_to_resolve;
/** default port to use */ /** default port to use */
char *default_port; char *default_port;
/** channel args. */
grpc_channel_args *channel_args;
/** mutex guarding the rest of the state */ /** mutex guarding the rest of the state */
gpr_mu mu; gpr_mu mu;
@ -71,9 +72,9 @@ typedef struct {
/** pending next completion, or NULL */ /** pending next completion, or NULL */
grpc_closure *next_completion; grpc_closure *next_completion;
/** target result address for next completion */ /** target result address for next completion */
grpc_resolver_result **target_result; grpc_channel_args **target_result;
/** current (fully resolved) result */ /** current (fully resolved) result */
grpc_resolver_result *resolved_result; grpc_channel_args *resolved_result;
/** retry timer */ /** retry timer */
bool have_retry_timer; bool have_retry_timer;
grpc_timer retry_timer; grpc_timer retry_timer;
@ -94,7 +95,7 @@ static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r); static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx, grpc_resolver *r); static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r, static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
grpc_resolver_result **target_result, grpc_channel_args **target_result,
grpc_closure *on_complete); grpc_closure *on_complete);
static const grpc_resolver_vtable dns_resolver_vtable = { static const grpc_resolver_vtable dns_resolver_vtable = {
@ -127,7 +128,7 @@ static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx,
} }
static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver, static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
grpc_resolver_result **target_result, grpc_channel_args **target_result,
grpc_closure *on_complete) { grpc_closure *on_complete) {
dns_resolver *r = (dns_resolver *)resolver; dns_resolver *r = (dns_resolver *)resolver;
gpr_mu_lock(&r->mu); gpr_mu_lock(&r->mu);
@ -162,22 +163,23 @@ static void dns_on_retry_timer(grpc_exec_ctx *exec_ctx, void *arg,
static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg, static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) { grpc_error *error) {
dns_resolver *r = arg; dns_resolver *r = arg;
grpc_resolver_result *result = NULL; grpc_channel_args *result = NULL;
gpr_mu_lock(&r->mu); gpr_mu_lock(&r->mu);
GPR_ASSERT(r->resolving); GPR_ASSERT(r->resolving);
r->resolving = false; r->resolving = false;
if (r->addresses != NULL) { if (r->addresses != NULL) {
grpc_lb_addresses *addresses = grpc_lb_addresses *addresses = grpc_lb_addresses_create(
grpc_lb_addresses_create(r->addresses->naddrs); r->addresses->naddrs, NULL /* user_data_vtable */);
for (size_t i = 0; i < r->addresses->naddrs; ++i) { for (size_t i = 0; i < r->addresses->naddrs; ++i) {
grpc_lb_addresses_set_address( grpc_lb_addresses_set_address(
addresses, i, &r->addresses->addrs[i].addr, addresses, i, &r->addresses->addrs[i].addr,
r->addresses->addrs[i].len, false /* is_balancer */, r->addresses->addrs[i].len, false /* is_balancer */,
NULL /* balancer_name */, NULL /* user_data */); NULL /* balancer_name */, NULL /* user_data */);
} }
grpc_arg new_arg = grpc_lb_addresses_create_channel_arg(addresses);
result = grpc_channel_args_copy_and_add(r->channel_args, &new_arg, 1);
grpc_resolved_addresses_destroy(r->addresses); grpc_resolved_addresses_destroy(r->addresses);
result = grpc_resolver_result_create(r->target_name, addresses, grpc_lb_addresses_destroy(addresses);
NULL /* lb_policy_name */, NULL);
} else { } else {
gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
gpr_timespec next_try = gpr_backoff_step(&r->backoff_state, now); gpr_timespec next_try = gpr_backoff_step(&r->backoff_state, now);
@ -197,8 +199,8 @@ static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
grpc_timer_init(exec_ctx, &r->retry_timer, next_try, dns_on_retry_timer, r, grpc_timer_init(exec_ctx, &r->retry_timer, next_try, dns_on_retry_timer, r,
now); now);
} }
if (r->resolved_result) { if (r->resolved_result != NULL) {
grpc_resolver_result_unref(exec_ctx, r->resolved_result); grpc_channel_args_destroy(r->resolved_result);
} }
r->resolved_result = result; r->resolved_result = result;
r->resolved_version++; r->resolved_version++;
@ -222,10 +224,9 @@ static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
dns_resolver *r) { dns_resolver *r) {
if (r->next_completion != NULL && if (r->next_completion != NULL &&
r->resolved_version != r->published_version) { r->resolved_version != r->published_version) {
*r->target_result = r->resolved_result; *r->target_result = r->resolved_result == NULL
if (r->resolved_result) { ? NULL
grpc_resolver_result_ref(r->resolved_result); : grpc_channel_args_copy(r->resolved_result);
}
grpc_exec_ctx_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE, NULL); grpc_exec_ctx_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE, NULL);
r->next_completion = NULL; r->next_completion = NULL;
r->published_version = r->resolved_version; r->published_version = r->resolved_version;
@ -235,12 +236,12 @@ static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) { static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
dns_resolver *r = (dns_resolver *)gr; dns_resolver *r = (dns_resolver *)gr;
gpr_mu_destroy(&r->mu); gpr_mu_destroy(&r->mu);
if (r->resolved_result) { if (r->resolved_result != NULL) {
grpc_resolver_result_unref(exec_ctx, r->resolved_result); grpc_channel_args_destroy(r->resolved_result);
} }
gpr_free(r->target_name);
gpr_free(r->name_to_resolve); gpr_free(r->name_to_resolve);
gpr_free(r->default_port); gpr_free(r->default_port);
grpc_channel_args_destroy(r->channel_args);
gpr_free(r); gpr_free(r);
} }
@ -260,9 +261,14 @@ static grpc_resolver *dns_create(grpc_resolver_args *args,
memset(r, 0, sizeof(*r)); memset(r, 0, sizeof(*r));
gpr_mu_init(&r->mu); gpr_mu_init(&r->mu);
grpc_resolver_init(&r->base, &dns_resolver_vtable); grpc_resolver_init(&r->base, &dns_resolver_vtable);
r->target_name = gpr_strdup(path);
r->name_to_resolve = proxy_name == NULL ? gpr_strdup(path) : proxy_name; r->name_to_resolve = proxy_name == NULL ? gpr_strdup(path) : proxy_name;
r->default_port = gpr_strdup(default_port); r->default_port = gpr_strdup(default_port);
grpc_arg server_name_arg;
server_name_arg.type = GRPC_ARG_STRING;
server_name_arg.key = GRPC_ARG_SERVER_NAME;
server_name_arg.value.string = (char *)path;
r->channel_args =
grpc_channel_args_copy_and_add(args->args, &server_name_arg, 1);
gpr_backoff_init(&r->backoff_state, BACKOFF_MULTIPLIER, BACKOFF_JITTER, gpr_backoff_init(&r->backoff_state, BACKOFF_MULTIPLIER, BACKOFF_JITTER,
BACKOFF_MIN_SECONDS * 1000, BACKOFF_MAX_SECONDS * 1000); BACKOFF_MIN_SECONDS * 1000, BACKOFF_MAX_SECONDS * 1000);
return &r->base; return &r->base;

@ -41,8 +41,10 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#include "src/core/ext/client_channel/lb_policy_factory.h"
#include "src/core/ext/client_channel/parse_address.h" #include "src/core/ext/client_channel/parse_address.h"
#include "src/core/ext/client_channel/resolver_registry.h" #include "src/core/ext/client_channel/resolver_registry.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/unix_sockets_posix.h" #include "src/core/lib/iomgr/unix_sockets_posix.h"
#include "src/core/lib/support/string.h" #include "src/core/lib/support/string.h"
@ -50,10 +52,10 @@
typedef struct { typedef struct {
/** base class: must be first */ /** base class: must be first */
grpc_resolver base; grpc_resolver base;
/** the path component of the uri passed in */
char *target_name;
/** the addresses that we've 'resolved' */ /** the addresses that we've 'resolved' */
grpc_lb_addresses *addresses; grpc_lb_addresses *addresses;
/** channel args */
grpc_channel_args *channel_args;
/** mutex guarding the rest of the state */ /** mutex guarding the rest of the state */
gpr_mu mu; gpr_mu mu;
/** have we published? */ /** have we published? */
@ -61,7 +63,7 @@ typedef struct {
/** pending next completion, or NULL */ /** pending next completion, or NULL */
grpc_closure *next_completion; grpc_closure *next_completion;
/** target result address for next completion */ /** target result address for next completion */
grpc_resolver_result **target_result; grpc_channel_args **target_result;
} sockaddr_resolver; } sockaddr_resolver;
static void sockaddr_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r); static void sockaddr_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
@ -73,7 +75,7 @@ static void sockaddr_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
static void sockaddr_channel_saw_error(grpc_exec_ctx *exec_ctx, static void sockaddr_channel_saw_error(grpc_exec_ctx *exec_ctx,
grpc_resolver *r); grpc_resolver *r);
static void sockaddr_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r, static void sockaddr_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
grpc_resolver_result **target_result, grpc_channel_args **target_result,
grpc_closure *on_complete); grpc_closure *on_complete);
static const grpc_resolver_vtable sockaddr_resolver_vtable = { static const grpc_resolver_vtable sockaddr_resolver_vtable = {
@ -102,7 +104,7 @@ static void sockaddr_channel_saw_error(grpc_exec_ctx *exec_ctx,
} }
static void sockaddr_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver, static void sockaddr_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
grpc_resolver_result **target_result, grpc_channel_args **target_result,
grpc_closure *on_complete) { grpc_closure *on_complete) {
sockaddr_resolver *r = (sockaddr_resolver *)resolver; sockaddr_resolver *r = (sockaddr_resolver *)resolver;
gpr_mu_lock(&r->mu); gpr_mu_lock(&r->mu);
@ -117,10 +119,9 @@ static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
sockaddr_resolver *r) { sockaddr_resolver *r) {
if (r->next_completion != NULL && !r->published) { if (r->next_completion != NULL && !r->published) {
r->published = true; r->published = true;
*r->target_result = grpc_resolver_result_create( grpc_arg arg = grpc_lb_addresses_create_channel_arg(r->addresses);
r->target_name, *r->target_result =
grpc_lb_addresses_copy(r->addresses, NULL /* user_data_copy */), grpc_channel_args_copy_and_add(r->channel_args, &arg, 1);
NULL /* lb_policy_name */, NULL /* lb_policy_args */);
grpc_exec_ctx_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE, NULL); grpc_exec_ctx_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE, NULL);
r->next_completion = NULL; r->next_completion = NULL;
} }
@ -129,8 +130,8 @@ static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
static void sockaddr_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) { static void sockaddr_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
sockaddr_resolver *r = (sockaddr_resolver *)gr; sockaddr_resolver *r = (sockaddr_resolver *)gr;
gpr_mu_destroy(&r->mu); gpr_mu_destroy(&r->mu);
gpr_free(r->target_name); grpc_lb_addresses_destroy(r->addresses);
grpc_lb_addresses_destroy(r->addresses, NULL /* user_data_destroy */); grpc_channel_args_destroy(r->channel_args);
gpr_free(r); gpr_free(r);
} }
@ -173,7 +174,8 @@ static grpc_resolver *sockaddr_create(grpc_resolver_args *args,
gpr_slice_buffer path_parts; gpr_slice_buffer path_parts;
gpr_slice_buffer_init(&path_parts); gpr_slice_buffer_init(&path_parts);
gpr_slice_split(path_slice, ",", &path_parts); gpr_slice_split(path_slice, ",", &path_parts);
grpc_lb_addresses *addresses = grpc_lb_addresses_create(path_parts.count); grpc_lb_addresses *addresses =
grpc_lb_addresses_create(path_parts.count, NULL /* user_data_vtable */);
bool errors_found = false; bool errors_found = false;
for (size_t i = 0; i < addresses->num_addresses; i++) { for (size_t i = 0; i < addresses->num_addresses; i++) {
grpc_uri ith_uri = *args->uri; grpc_uri ith_uri = *args->uri;
@ -188,14 +190,19 @@ static grpc_resolver *sockaddr_create(grpc_resolver_args *args,
gpr_slice_buffer_destroy(&path_parts); gpr_slice_buffer_destroy(&path_parts);
gpr_slice_unref(path_slice); gpr_slice_unref(path_slice);
if (errors_found) { if (errors_found) {
grpc_lb_addresses_destroy(addresses, NULL /* user_data_destroy */); grpc_lb_addresses_destroy(addresses);
return NULL; return NULL;
} }
/* Instantiate resolver. */ /* Instantiate resolver. */
sockaddr_resolver *r = gpr_malloc(sizeof(sockaddr_resolver)); sockaddr_resolver *r = gpr_malloc(sizeof(sockaddr_resolver));
memset(r, 0, sizeof(*r)); memset(r, 0, sizeof(*r));
r->target_name = gpr_strdup(args->uri->path);
r->addresses = addresses; r->addresses = addresses;
grpc_arg server_name_arg;
server_name_arg.type = GRPC_ARG_STRING;
server_name_arg.key = GRPC_ARG_SERVER_NAME;
server_name_arg.value.string = args->uri->path;
r->channel_args =
grpc_channel_args_copy_and_add(args->args, &server_name_arg, 1);
gpr_mu_init(&r->mu); gpr_mu_init(&r->mu);
grpc_resolver_init(&r->base, &sockaddr_resolver_vtable); grpc_resolver_init(&r->base, &sockaddr_resolver_vtable);
return &r->base; return &r->base;

@ -52,6 +52,10 @@
#include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/api_trace.h"
#include "src/core/lib/surface/channel.h" #include "src/core/lib/surface/channel.h"
//
// connector
//
typedef struct { typedef struct {
grpc_connector base; grpc_connector base;
gpr_refcount refs; gpr_refcount refs;
@ -156,35 +160,20 @@ static void connector_connect(grpc_exec_ctx *exec_ctx, grpc_connector *con,
static const grpc_connector_vtable connector_vtable = { static const grpc_connector_vtable connector_vtable = {
connector_ref, connector_unref, connector_shutdown, connector_connect}; connector_ref, connector_unref, connector_shutdown, connector_connect};
typedef struct { //
grpc_client_channel_factory base; // client_channel_factory
gpr_refcount refs; //
grpc_channel_args *merge_args;
} client_channel_factory;
static void client_channel_factory_ref( static void client_channel_factory_ref(
grpc_client_channel_factory *cc_factory) { grpc_client_channel_factory *cc_factory) {}
client_channel_factory *f = (client_channel_factory *)cc_factory;
gpr_ref(&f->refs);
}
static void client_channel_factory_unref( static void client_channel_factory_unref(
grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory) { grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory) {}
client_channel_factory *f = (client_channel_factory *)cc_factory;
if (gpr_unref(&f->refs)) {
grpc_channel_args_destroy(f->merge_args);
gpr_free(f);
}
}
static grpc_subchannel *client_channel_factory_create_subchannel( static grpc_subchannel *client_channel_factory_create_subchannel(
grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory, grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
grpc_subchannel_args *args) { const grpc_subchannel_args *args) {
client_channel_factory *f = (client_channel_factory *)cc_factory;
connector *c = gpr_malloc(sizeof(*c)); connector *c = gpr_malloc(sizeof(*c));
grpc_channel_args *final_args =
grpc_channel_args_merge(args->args, f->merge_args);
grpc_subchannel *s;
memset(c, 0, sizeof(*c)); memset(c, 0, sizeof(*c));
c->base.vtable = &connector_vtable; c->base.vtable = &connector_vtable;
gpr_ref_init(&c->refs, 1); gpr_ref_init(&c->refs, 1);
@ -196,23 +185,18 @@ static grpc_subchannel *client_channel_factory_create_subchannel(
grpc_http_connect_handshaker_create(proxy_name, args->server_name)); grpc_http_connect_handshaker_create(proxy_name, args->server_name));
gpr_free(proxy_name); gpr_free(proxy_name);
} }
args->args = final_args; grpc_subchannel *s = grpc_subchannel_create(exec_ctx, &c->base, args);
s = grpc_subchannel_create(exec_ctx, &c->base, args);
grpc_connector_unref(exec_ctx, &c->base); grpc_connector_unref(exec_ctx, &c->base);
grpc_channel_args_destroy(final_args);
return s; return s;
} }
static grpc_channel *client_channel_factory_create_channel( static grpc_channel *client_channel_factory_create_channel(
grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory, grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
const char *target, grpc_client_channel_type type, const char *target, grpc_client_channel_type type,
grpc_channel_args *args) { const grpc_channel_args *args) {
client_channel_factory *f = (client_channel_factory *)cc_factory; grpc_channel *channel =
grpc_channel_args *final_args = grpc_channel_args_merge(args, f->merge_args); grpc_channel_create(exec_ctx, target, args, GRPC_CLIENT_CHANNEL, NULL);
grpc_channel *channel = grpc_channel_create(exec_ctx, target, final_args, grpc_resolver *resolver = grpc_resolver_create(target, args);
GRPC_CLIENT_CHANNEL, NULL);
grpc_channel_args_destroy(final_args);
grpc_resolver *resolver = grpc_resolver_create(target);
if (!resolver) { if (!resolver) {
GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel, GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel,
"client_channel_factory_create_channel"); "client_channel_factory_create_channel");
@ -220,7 +204,7 @@ static grpc_channel *client_channel_factory_create_channel(
} }
grpc_client_channel_finish_initialization( grpc_client_channel_finish_initialization(
exec_ctx, grpc_channel_get_channel_stack(channel), resolver, &f->base); exec_ctx, grpc_channel_get_channel_stack(channel), resolver, cc_factory);
GRPC_RESOLVER_UNREF(exec_ctx, resolver, "create_channel"); GRPC_RESOLVER_UNREF(exec_ctx, resolver, "create_channel");
return channel; return channel;
@ -231,6 +215,9 @@ static const grpc_client_channel_factory_vtable client_channel_factory_vtable =
client_channel_factory_create_subchannel, client_channel_factory_create_subchannel,
client_channel_factory_create_channel}; client_channel_factory_create_channel};
static grpc_client_channel_factory client_channel_factory = {
&client_channel_factory_vtable};
/* Create a client channel: /* Create a client channel:
Asynchronously: - resolve target Asynchronously: - resolve target
- connect to it (trying alternatives as presented) - connect to it (trying alternatives as presented)
@ -244,16 +231,12 @@ grpc_channel *grpc_insecure_channel_create(const char *target,
(target, args, reserved)); (target, args, reserved));
GPR_ASSERT(!reserved); GPR_ASSERT(!reserved);
client_channel_factory *f = gpr_malloc(sizeof(*f)); grpc_client_channel_factory *factory =
memset(f, 0, sizeof(*f)); (grpc_client_channel_factory *)&client_channel_factory;
f->base.vtable = &client_channel_factory_vtable;
gpr_ref_init(&f->refs, 1);
f->merge_args = grpc_channel_args_copy(args);
grpc_channel *channel = client_channel_factory_create_channel( grpc_channel *channel = client_channel_factory_create_channel(
&exec_ctx, &f->base, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR, NULL); &exec_ctx, factory, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR, args);
grpc_client_channel_factory_unref(&exec_ctx, &f->base); grpc_client_channel_factory_unref(&exec_ctx, factory);
grpc_exec_ctx_finish(&exec_ctx); grpc_exec_ctx_finish(&exec_ctx);
return channel != NULL ? channel : grpc_lame_client_channel_create( return channel != NULL ? channel : grpc_lame_client_channel_create(

@ -54,6 +54,10 @@
#include "src/core/lib/surface/channel.h" #include "src/core/lib/surface/channel.h"
#include "src/core/lib/tsi/transport_security_interface.h" #include "src/core/lib/tsi/transport_security_interface.h"
//
// connector
//
typedef struct { typedef struct {
grpc_connector base; grpc_connector base;
gpr_refcount refs; gpr_refcount refs;
@ -216,10 +220,13 @@ static void connector_connect(grpc_exec_ctx *exec_ctx, grpc_connector *con,
static const grpc_connector_vtable connector_vtable = { static const grpc_connector_vtable connector_vtable = {
connector_ref, connector_unref, connector_shutdown, connector_connect}; connector_ref, connector_unref, connector_shutdown, connector_connect};
//
// client_channel_factory
//
typedef struct { typedef struct {
grpc_client_channel_factory base; grpc_client_channel_factory base;
gpr_refcount refs; gpr_refcount refs;
grpc_channel_args *merge_args;
grpc_channel_security_connector *security_connector; grpc_channel_security_connector *security_connector;
} client_channel_factory; } client_channel_factory;
@ -235,19 +242,15 @@ static void client_channel_factory_unref(
if (gpr_unref(&f->refs)) { if (gpr_unref(&f->refs)) {
GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base, GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base,
"client_channel_factory"); "client_channel_factory");
grpc_channel_args_destroy(f->merge_args);
gpr_free(f); gpr_free(f);
} }
} }
static grpc_subchannel *client_channel_factory_create_subchannel( static grpc_subchannel *client_channel_factory_create_subchannel(
grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory, grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
grpc_subchannel_args *args) { const grpc_subchannel_args *args) {
client_channel_factory *f = (client_channel_factory *)cc_factory; client_channel_factory *f = (client_channel_factory *)cc_factory;
connector *c = gpr_malloc(sizeof(*c)); connector *c = gpr_malloc(sizeof(*c));
grpc_channel_args *final_args =
grpc_channel_args_merge(args->args, f->merge_args);
grpc_subchannel *s;
memset(c, 0, sizeof(*c)); memset(c, 0, sizeof(*c));
c->base.vtable = &connector_vtable; c->base.vtable = &connector_vtable;
c->security_connector = f->security_connector; c->security_connector = f->security_connector;
@ -261,25 +264,19 @@ static grpc_subchannel *client_channel_factory_create_subchannel(
} }
gpr_mu_init(&c->mu); gpr_mu_init(&c->mu);
gpr_ref_init(&c->refs, 1); gpr_ref_init(&c->refs, 1);
args->args = final_args; grpc_subchannel *s = grpc_subchannel_create(exec_ctx, &c->base, args);
s = grpc_subchannel_create(exec_ctx, &c->base, args);
grpc_connector_unref(exec_ctx, &c->base); grpc_connector_unref(exec_ctx, &c->base);
grpc_channel_args_destroy(final_args);
return s; return s;
} }
static grpc_channel *client_channel_factory_create_channel( static grpc_channel *client_channel_factory_create_channel(
grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory, grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
const char *target, grpc_client_channel_type type, const char *target, grpc_client_channel_type type,
grpc_channel_args *args) { const grpc_channel_args *args) {
client_channel_factory *f = (client_channel_factory *)cc_factory; client_channel_factory *f = (client_channel_factory *)cc_factory;
grpc_channel *channel =
grpc_channel_args *final_args = grpc_channel_args_merge(args, f->merge_args); grpc_channel_create(exec_ctx, target, args, GRPC_CLIENT_CHANNEL, NULL);
grpc_channel *channel = grpc_channel_create(exec_ctx, target, final_args, grpc_resolver *resolver = grpc_resolver_create(target, args);
GRPC_CLIENT_CHANNEL, NULL);
grpc_channel_args_destroy(final_args);
grpc_resolver *resolver = grpc_resolver_create(target);
if (resolver != NULL) { if (resolver != NULL) {
grpc_client_channel_finish_initialization( grpc_client_channel_finish_initialization(
exec_ctx, grpc_channel_get_channel_stack(channel), resolver, &f->base); exec_ctx, grpc_channel_get_channel_stack(channel), resolver, &f->base);
@ -289,7 +286,6 @@ static grpc_channel *client_channel_factory_create_channel(
"client_channel_factory_create_channel"); "client_channel_factory_create_channel");
channel = NULL; channel = NULL;
} }
return channel; return channel;
} }
@ -306,19 +302,13 @@ grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds,
const char *target, const char *target,
const grpc_channel_args *args, const grpc_channel_args *args,
void *reserved) { void *reserved) {
grpc_arg connector_arg;
grpc_channel_args *args_copy;
grpc_channel_args *new_args_from_connector;
grpc_channel_security_connector *security_connector;
client_channel_factory *f;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
GRPC_API_TRACE( GRPC_API_TRACE(
"grpc_secure_channel_create(creds=%p, target=%s, args=%p, " "grpc_secure_channel_create(creds=%p, target=%s, args=%p, "
"reserved=%p)", "reserved=%p)",
4, (creds, target, args, reserved)); 4, (creds, target, args, reserved));
GPR_ASSERT(reserved == NULL); GPR_ASSERT(reserved == NULL);
// Make sure security connector does not already exist in args.
if (grpc_find_security_connector_in_args(args) != NULL) { if (grpc_find_security_connector_in_args(args) != NULL) {
gpr_log(GPR_ERROR, "Cannot set security context in channel args."); gpr_log(GPR_ERROR, "Cannot set security context in channel args.");
grpc_exec_ctx_finish(&exec_ctx); grpc_exec_ctx_finish(&exec_ctx);
@ -326,7 +316,9 @@ grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds,
target, GRPC_STATUS_INTERNAL, target, GRPC_STATUS_INTERNAL,
"Security connector exists in channel args."); "Security connector exists in channel args.");
} }
// Create security connector and construct new channel args.
grpc_channel_security_connector *security_connector;
grpc_channel_args *new_args_from_connector;
if (grpc_channel_credentials_create_security_connector( if (grpc_channel_credentials_create_security_connector(
creds, target, args, &security_connector, &new_args_from_connector) != creds, target, args, &security_connector, &new_args_from_connector) !=
GRPC_SECURITY_OK) { GRPC_SECURITY_OK) {
@ -334,35 +326,30 @@ grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds,
return grpc_lame_client_channel_create( return grpc_lame_client_channel_create(
target, GRPC_STATUS_INTERNAL, "Failed to create security connector."); target, GRPC_STATUS_INTERNAL, "Failed to create security connector.");
} }
grpc_arg connector_arg =
connector_arg = grpc_security_connector_to_arg(&security_connector->base); grpc_security_connector_to_arg(&security_connector->base);
args_copy = grpc_channel_args_copy_and_add( grpc_channel_args *new_args = grpc_channel_args_copy_and_add(
new_args_from_connector != NULL ? new_args_from_connector : args, new_args_from_connector != NULL ? new_args_from_connector : args,
&connector_arg, 1); &connector_arg, 1);
f = gpr_malloc(sizeof(*f));
memset(f, 0, sizeof(*f));
f->base.vtable = &client_channel_factory_vtable;
gpr_ref_init(&f->refs, 1);
f->merge_args = grpc_channel_args_copy(args_copy);
grpc_channel_args_destroy(args_copy);
if (new_args_from_connector != NULL) { if (new_args_from_connector != NULL) {
grpc_channel_args_destroy(new_args_from_connector); grpc_channel_args_destroy(new_args_from_connector);
} }
// Create client channel factory.
client_channel_factory *f = gpr_malloc(sizeof(*f));
memset(f, 0, sizeof(*f));
f->base.vtable = &client_channel_factory_vtable;
gpr_ref_init(&f->refs, 1);
GRPC_SECURITY_CONNECTOR_REF(&security_connector->base, GRPC_SECURITY_CONNECTOR_REF(&security_connector->base,
"grpc_secure_channel_create"); "grpc_secure_channel_create");
f->security_connector = security_connector; f->security_connector = security_connector;
// Create channel.
grpc_channel *channel = client_channel_factory_create_channel( grpc_channel *channel = client_channel_factory_create_channel(
&exec_ctx, &f->base, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR, NULL); &exec_ctx, &f->base, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR, new_args);
// Clean up.
GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base, GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base,
"client_channel_factory_create_channel"); "client_channel_factory_create_channel");
grpc_channel_args_destroy(new_args);
grpc_client_channel_factory_unref(&exec_ctx, &f->base); grpc_client_channel_factory_unref(&exec_ctx, &f->base);
grpc_exec_ctx_finish(&exec_ctx); grpc_exec_ctx_finish(&exec_ctx);
return channel; /* may be NULL */ return channel; /* may be NULL */
} }

@ -66,22 +66,59 @@ static grpc_arg copy_arg(const grpc_arg *src) {
grpc_channel_args *grpc_channel_args_copy_and_add(const grpc_channel_args *src, grpc_channel_args *grpc_channel_args_copy_and_add(const grpc_channel_args *src,
const grpc_arg *to_add, const grpc_arg *to_add,
size_t num_to_add) { size_t num_to_add) {
return grpc_channel_args_copy_and_add_and_remove(src, NULL, 0, to_add,
num_to_add);
}
grpc_channel_args *grpc_channel_args_copy_and_remove(
const grpc_channel_args *src, const char **to_remove,
size_t num_to_remove) {
return grpc_channel_args_copy_and_add_and_remove(src, to_remove,
num_to_remove, NULL, 0);
}
static bool should_remove_arg(const grpc_arg *arg, const char **to_remove,
size_t num_to_remove) {
for (size_t i = 0; i < num_to_remove; ++i) {
if (strcmp(arg->key, to_remove[i]) == 0) return true;
}
return false;
}
grpc_channel_args *grpc_channel_args_copy_and_add_and_remove(
const grpc_channel_args *src, const char **to_remove, size_t num_to_remove,
const grpc_arg *to_add, size_t num_to_add) {
// Figure out how many args we'll be copying.
size_t num_args_to_copy = 0;
if (src != NULL) {
for (size_t i = 0; i < src->num_args; ++i) {
if (!should_remove_arg(&src->args[i], to_remove, num_to_remove)) {
++num_args_to_copy;
}
}
}
// Create result.
grpc_channel_args *dst = gpr_malloc(sizeof(grpc_channel_args)); grpc_channel_args *dst = gpr_malloc(sizeof(grpc_channel_args));
size_t i; dst->num_args = num_args_to_copy + num_to_add;
size_t src_num_args = (src == NULL) ? 0 : src->num_args; if (dst->num_args == 0) {
if (!src && !to_add) {
dst->num_args = 0;
dst->args = NULL; dst->args = NULL;
return dst; return dst;
} }
dst->num_args = src_num_args + num_to_add;
dst->args = gpr_malloc(sizeof(grpc_arg) * dst->num_args); dst->args = gpr_malloc(sizeof(grpc_arg) * dst->num_args);
for (i = 0; i < src_num_args; i++) { // Copy args from src that are not being removed.
dst->args[i] = copy_arg(&src->args[i]); size_t dst_idx = 0;
if (src != NULL) {
for (size_t i = 0; i < src->num_args; ++i) {
if (!should_remove_arg(&src->args[i], to_remove, num_to_remove)) {
dst->args[dst_idx++] = copy_arg(&src->args[i]);
}
}
} }
for (i = 0; i < num_to_add; i++) { // Add args from to_add.
dst->args[i + src_num_args] = copy_arg(&to_add[i]); for (size_t i = 0; i < num_to_add; ++i) {
dst->args[dst_idx++] = copy_arg(&to_add[i]);
} }
GPR_ASSERT(dst_idx == dst->num_args);
return dst; return dst;
} }

@ -51,6 +51,17 @@ grpc_channel_args *grpc_channel_args_copy_and_add(const grpc_channel_args *src,
const grpc_arg *to_add, const grpc_arg *to_add,
size_t num_to_add); size_t num_to_add);
/** Copies the arguments in \a src except for those whose keys are in
\a to_remove. */
grpc_channel_args *grpc_channel_args_copy_and_remove(
const grpc_channel_args *src, const char **to_remove, size_t num_to_remove);
/** Copies the arguments from \a src except for those whose keys are in
\a to_remove and appends the arguments in \a to_add. */
grpc_channel_args *grpc_channel_args_copy_and_add_and_remove(
const grpc_channel_args *src, const char **to_remove, size_t num_to_remove,
const grpc_arg *to_add, size_t num_to_add);
/** Concatenate args from \a a and \a b into a new instance */ /** Concatenate args from \a a and \a b into a new instance */
grpc_channel_args *grpc_channel_args_merge(const grpc_channel_args *a, grpc_channel_args *grpc_channel_args_merge(const grpc_channel_args *a,
const grpc_channel_args *b); const grpc_channel_args *b);

@ -45,10 +45,6 @@ namespace Grpc.Core.Internal
{ {
} }
public SafeHandleZeroIsInvalid(bool ownsHandle) : base(IntPtr.Zero, ownsHandle)
{
}
public override bool IsInvalid public override bool IsInvalid
{ {
get get
@ -56,11 +52,5 @@ namespace Grpc.Core.Internal
return handle == IntPtr.Zero; return handle == IntPtr.Zero;
} }
} }
protected override bool ReleaseHandle()
{
// handle is not owned.
return true;
}
} }
} }

@ -76,7 +76,7 @@ namespace Grpc.Core.Internal
Status status; Status status;
Tuple<TResponse,WriteFlags> responseTuple = null; Tuple<TResponse,WriteFlags> responseTuple = null;
var context = HandlerUtils.NewContext(newRpc, asyncCall.Peer, responseStream, asyncCall.CancellationToken); var context = HandlerUtils.NewContext(newRpc, responseStream, asyncCall.CancellationToken);
try try
{ {
GrpcPreconditions.CheckArgument(await requestStream.MoveNext().ConfigureAwait(false)); GrpcPreconditions.CheckArgument(await requestStream.MoveNext().ConfigureAwait(false));
@ -134,7 +134,7 @@ namespace Grpc.Core.Internal
var responseStream = new ServerResponseStream<TRequest, TResponse>(asyncCall); var responseStream = new ServerResponseStream<TRequest, TResponse>(asyncCall);
Status status; Status status;
var context = HandlerUtils.NewContext(newRpc, asyncCall.Peer, responseStream, asyncCall.CancellationToken); var context = HandlerUtils.NewContext(newRpc, responseStream, asyncCall.CancellationToken);
try try
{ {
GrpcPreconditions.CheckArgument(await requestStream.MoveNext().ConfigureAwait(false)); GrpcPreconditions.CheckArgument(await requestStream.MoveNext().ConfigureAwait(false));
@ -193,7 +193,7 @@ namespace Grpc.Core.Internal
Status status; Status status;
Tuple<TResponse,WriteFlags> responseTuple = null; Tuple<TResponse,WriteFlags> responseTuple = null;
var context = HandlerUtils.NewContext(newRpc, asyncCall.Peer, responseStream, asyncCall.CancellationToken); var context = HandlerUtils.NewContext(newRpc, responseStream, asyncCall.CancellationToken);
try try
{ {
var response = await handler(requestStream, context).ConfigureAwait(false); var response = await handler(requestStream, context).ConfigureAwait(false);
@ -250,7 +250,7 @@ namespace Grpc.Core.Internal
var responseStream = new ServerResponseStream<TRequest, TResponse>(asyncCall); var responseStream = new ServerResponseStream<TRequest, TResponse>(asyncCall);
Status status; Status status;
var context = HandlerUtils.NewContext(newRpc, asyncCall.Peer, responseStream, asyncCall.CancellationToken); var context = HandlerUtils.NewContext(newRpc, responseStream, asyncCall.CancellationToken);
try try
{ {
await handler(requestStream, responseStream, context).ConfigureAwait(false); await handler(requestStream, responseStream, context).ConfigureAwait(false);
@ -324,13 +324,13 @@ namespace Grpc.Core.Internal
return writeOptions != null ? writeOptions.Flags : default(WriteFlags); return writeOptions != null ? writeOptions.Flags : default(WriteFlags);
} }
public static ServerCallContext NewContext<TRequest, TResponse>(ServerRpcNew newRpc, string peer, ServerResponseStream<TRequest, TResponse> serverResponseStream, CancellationToken cancellationToken) public static ServerCallContext NewContext<TRequest, TResponse>(ServerRpcNew newRpc, ServerResponseStream<TRequest, TResponse> serverResponseStream, CancellationToken cancellationToken)
where TRequest : class where TRequest : class
where TResponse : class where TResponse : class
{ {
DateTime realtimeDeadline = newRpc.Deadline.ToClockType(ClockType.Realtime).ToDateTime(); DateTime realtimeDeadline = newRpc.Deadline.ToClockType(ClockType.Realtime).ToDateTime();
return new ServerCallContext(newRpc.Call, newRpc.Method, newRpc.Host, peer, realtimeDeadline, return new ServerCallContext(newRpc.Call, newRpc.Method, newRpc.Host, realtimeDeadline,
newRpc.RequestMetadata, cancellationToken, serverResponseStream.WriteResponseHeadersAsync, serverResponseStream); newRpc.RequestMetadata, cancellationToken, serverResponseStream.WriteResponseHeadersAsync, serverResponseStream);
} }
} }

@ -48,7 +48,6 @@ namespace Grpc.Core
private readonly CallSafeHandle callHandle; private readonly CallSafeHandle callHandle;
private readonly string method; private readonly string method;
private readonly string host; private readonly string host;
private readonly string peer;
private readonly DateTime deadline; private readonly DateTime deadline;
private readonly Metadata requestHeaders; private readonly Metadata requestHeaders;
private readonly CancellationToken cancellationToken; private readonly CancellationToken cancellationToken;
@ -58,13 +57,12 @@ namespace Grpc.Core
private Func<Metadata, Task> writeHeadersFunc; private Func<Metadata, Task> writeHeadersFunc;
private IHasWriteOptions writeOptionsHolder; private IHasWriteOptions writeOptionsHolder;
internal ServerCallContext(CallSafeHandle callHandle, string method, string host, string peer, DateTime deadline, Metadata requestHeaders, CancellationToken cancellationToken, internal ServerCallContext(CallSafeHandle callHandle, string method, string host, DateTime deadline, Metadata requestHeaders, CancellationToken cancellationToken,
Func<Metadata, Task> writeHeadersFunc, IHasWriteOptions writeOptionsHolder) Func<Metadata, Task> writeHeadersFunc, IHasWriteOptions writeOptionsHolder)
{ {
this.callHandle = callHandle; this.callHandle = callHandle;
this.method = method; this.method = method;
this.host = host; this.host = host;
this.peer = peer;
this.deadline = deadline; this.deadline = deadline;
this.requestHeaders = requestHeaders; this.requestHeaders = requestHeaders;
this.cancellationToken = cancellationToken; this.cancellationToken = cancellationToken;
@ -115,7 +113,10 @@ namespace Grpc.Core
{ {
get get
{ {
return this.peer; // Getting the peer lazily is fine as the native call is guaranteed
// not to be disposed before user-supplied server side handler returns.
// Most users won't need to read this field anyway.
return this.callHandle.GetPeer();
} }
} }

@ -380,7 +380,6 @@ function unimplementedService(client, done) {
client.unimplementedCall({}, function(err, resp) { client.unimplementedCall({}, function(err, resp) {
assert(err); assert(err);
assert.strictEqual(err.code, grpc.status.UNIMPLEMENTED); assert.strictEqual(err.code, grpc.status.UNIMPLEMENTED);
assert(!err.message);
done(); done();
}); });
} }

@ -250,7 +250,6 @@ CORE_SOURCE_FILES = [
'src/core/ext/client_channel/resolver.c', 'src/core/ext/client_channel/resolver.c',
'src/core/ext/client_channel/resolver_factory.c', 'src/core/ext/client_channel/resolver_factory.c',
'src/core/ext/client_channel/resolver_registry.c', 'src/core/ext/client_channel/resolver_registry.c',
'src/core/ext/client_channel/resolver_result.c',
'src/core/ext/client_channel/subchannel.c', 'src/core/ext/client_channel/subchannel.c',
'src/core/ext/client_channel/subchannel_index.c', 'src/core/ext/client_channel/subchannel_index.c',
'src/core/ext/client_channel/uri_parser.c', 'src/core/ext/client_channel/uri_parser.c',

@ -106,7 +106,10 @@ def _stub(args):
(('grpc.ssl_target_name_override', args.server_host_override,),)) (('grpc.ssl_target_name_override', args.server_host_override,),))
else: else:
channel = grpc.insecure_channel(target) channel = grpc.insecure_channel(target)
return test_pb2.TestServiceStub(channel) if args.test_case == "unimplemented_service":
return test_pb2.UnimplementedServiceStub(channel)
else:
return test_pb2.TestServiceStub(channel)
def _test_case_from_arg(test_case_arg): def _test_case_from_arg(test_case_arg):

@ -44,25 +44,43 @@ from src.proto.grpc.testing import empty_pb2
from src.proto.grpc.testing import messages_pb2 from src.proto.grpc.testing import messages_pb2
from src.proto.grpc.testing import test_pb2 from src.proto.grpc.testing import test_pb2
_INITIAL_METADATA_KEY = "x-grpc-test-echo-initial"
_TRAILING_METADATA_KEY = "x-grpc-test-echo-trailing-bin"
def _maybe_echo_metadata(servicer_context):
"""Copies metadata from request to response if it is present."""
invocation_metadata = dict(servicer_context.invocation_metadata())
if _INITIAL_METADATA_KEY in invocation_metadata:
initial_metadatum = (
_INITIAL_METADATA_KEY, invocation_metadata[_INITIAL_METADATA_KEY])
servicer_context.send_initial_metadata((initial_metadatum,))
if _TRAILING_METADATA_KEY in invocation_metadata:
trailing_metadatum = (
_TRAILING_METADATA_KEY, invocation_metadata[_TRAILING_METADATA_KEY])
servicer_context.set_trailing_metadata((trailing_metadatum,))
def _maybe_echo_status_and_message(request, servicer_context):
"""Sets the response context code and details if the request asks for them"""
if request.HasField('response_status'):
servicer_context.set_code(request.response_status.code)
servicer_context.set_details(request.response_status.message)
class TestService(test_pb2.TestServiceServicer): class TestService(test_pb2.TestServiceServicer):
def EmptyCall(self, request, context): def EmptyCall(self, request, context):
_maybe_echo_metadata(context)
return empty_pb2.Empty() return empty_pb2.Empty()
def UnaryCall(self, request, context): def UnaryCall(self, request, context):
if request.HasField('response_status'): _maybe_echo_metadata(context)
context.set_code(request.response_status.code) _maybe_echo_status_and_message(request, context)
context.set_details(request.response_status.message)
return messages_pb2.SimpleResponse( return messages_pb2.SimpleResponse(
payload=messages_pb2.Payload( payload=messages_pb2.Payload(
type=messages_pb2.COMPRESSABLE, type=messages_pb2.COMPRESSABLE,
body=b'\x00' * request.response_size)) body=b'\x00' * request.response_size))
def StreamingOutputCall(self, request, context): def StreamingOutputCall(self, request, context):
if request.HasField('response_status'): _maybe_echo_status_and_message(request, context)
context.set_code(request.response_status.code)
context.set_details(request.response_status.message)
for response_parameters in request.response_parameters: for response_parameters in request.response_parameters:
yield messages_pb2.StreamingOutputCallResponse( yield messages_pb2.StreamingOutputCallResponse(
payload=messages_pb2.Payload( payload=messages_pb2.Payload(
@ -78,10 +96,9 @@ class TestService(test_pb2.TestServiceServicer):
aggregated_payload_size=aggregate_size) aggregated_payload_size=aggregate_size)
def FullDuplexCall(self, request_iterator, context): def FullDuplexCall(self, request_iterator, context):
_maybe_echo_metadata(context)
for request in request_iterator: for request in request_iterator:
if request.HasField('response_status'): _maybe_echo_status_and_message(request, context)
context.set_code(request.response_status.code)
context.set_details(request.response_status.message)
for response_parameters in request.response_parameters: for response_parameters in request.response_parameters:
yield messages_pb2.StreamingOutputCallResponse( yield messages_pb2.StreamingOutputCallResponse(
payload=messages_pb2.Payload( payload=messages_pb2.Payload(
@ -94,23 +111,46 @@ class TestService(test_pb2.TestServiceServicer):
return self.FullDuplexCall(request_iterator, context) return self.FullDuplexCall(request_iterator, context)
def _expect_status_code(call, expected_code):
if call.code() != expected_code:
raise ValueError(
'expected code %s, got %s' % (expected_code, call.code()))
def _expect_status_details(call, expected_details):
if call.details() != expected_details:
raise ValueError(
'expected message %s, got %s' % (expected_details, call.details()))
def _validate_status_code_and_details(call, expected_code, expected_details):
_expect_status_code(call, expected_code)
_expect_status_details(call, expected_details)
def _validate_payload_type_and_length(response, expected_type, expected_length):
if response.payload.type is not expected_type:
raise ValueError(
'expected payload type %s, got %s' %
(expected_type, type(response.payload.type)))
elif len(response.payload.body) != expected_length:
raise ValueError(
'expected payload body size %d, got %d' %
(expected_length, len(response.payload.body)))
def _large_unary_common_behavior( def _large_unary_common_behavior(
stub, fill_username, fill_oauth_scope, call_credentials): stub, fill_username, fill_oauth_scope, call_credentials):
size = 314159
request = messages_pb2.SimpleRequest( request = messages_pb2.SimpleRequest(
response_type=messages_pb2.COMPRESSABLE, response_size=314159, response_type=messages_pb2.COMPRESSABLE, response_size=size,
payload=messages_pb2.Payload(body=b'\x00' * 271828), payload=messages_pb2.Payload(body=b'\x00' * 271828),
fill_username=fill_username, fill_oauth_scope=fill_oauth_scope) fill_username=fill_username, fill_oauth_scope=fill_oauth_scope)
response_future = stub.UnaryCall.future( response_future = stub.UnaryCall.future(
request, credentials=call_credentials) request, credentials=call_credentials)
response = response_future.result() response = response_future.result()
if response.payload.type is not messages_pb2.COMPRESSABLE: _validate_payload_type_and_length(response, messages_pb2.COMPRESSABLE, size)
raise ValueError( return response
'response payload type is "%s"!' % type(response.payload.type))
elif len(response.payload.body) != 314159:
raise ValueError(
'response body of incorrect size %d!' % len(response.payload.body))
else:
return response
def _empty_unary(stub): def _empty_unary(stub):
@ -152,12 +192,9 @@ def _server_streaming(stub):
) )
response_iterator = stub.StreamingOutputCall(request) response_iterator = stub.StreamingOutputCall(request)
for index, response in enumerate(response_iterator): for index, response in enumerate(response_iterator):
if response.payload.type != messages_pb2.COMPRESSABLE: _validate_payload_type_and_length(
raise ValueError( response, messages_pb2.COMPRESSABLE, sizes[index])
'response body of invalid type %s!' % response.payload.type)
elif len(response.payload.body) != sizes[index]:
raise ValueError(
'response body of invalid size %d!' % len(response.payload.body))
def _cancel_after_begin(stub): def _cancel_after_begin(stub):
sizes = (27182, 8, 1828, 45904,) sizes = (27182, 8, 1828, 45904,)
@ -224,12 +261,8 @@ def _ping_pong(stub):
payload=messages_pb2.Payload(body=b'\x00' * payload_size)) payload=messages_pb2.Payload(body=b'\x00' * payload_size))
pipe.add(request) pipe.add(request)
response = next(response_iterator) response = next(response_iterator)
if response.payload.type != messages_pb2.COMPRESSABLE: _validate_payload_type_and_length(
raise ValueError( response, messages_pb2.COMPRESSABLE, response_size)
'response body of invalid type %s!' % response.payload.type)
if len(response.payload.body) != response_size:
raise ValueError(
'response body of invalid size %d!' % len(response.payload.body))
def _cancel_after_first_response(stub): def _cancel_after_first_response(stub):
@ -291,36 +324,84 @@ def _empty_stream(stub):
def _status_code_and_message(stub): def _status_code_and_message(stub):
message = 'test status message' details = 'test status message'
code = 2 code = 2
status = grpc.StatusCode.UNKNOWN # code = 2 status = grpc.StatusCode.UNKNOWN # code = 2
# Test with a UnaryCall
request = messages_pb2.SimpleRequest( request = messages_pb2.SimpleRequest(
response_type=messages_pb2.COMPRESSABLE, response_type=messages_pb2.COMPRESSABLE,
response_size=1, response_size=1,
payload=messages_pb2.Payload(body=b'\x00'), payload=messages_pb2.Payload(body=b'\x00'),
response_status=messages_pb2.EchoStatus(code=code, message=message) response_status=messages_pb2.EchoStatus(code=code, message=details)
) )
response_future = stub.UnaryCall.future(request) response_future = stub.UnaryCall.future(request)
if response_future.code() != status: _validate_status_code_and_details(response_future, status, details)
raise ValueError(
'expected code %s, got %s' % (status, response_future.code()))
elif response_future.details() != message:
raise ValueError(
'expected message %s, got %s' % (message, response_future.details()))
request = messages_pb2.StreamingOutputCallRequest( # Test with a FullDuplexCall
with _Pipe() as pipe:
response_iterator = stub.FullDuplexCall(pipe)
request = messages_pb2.StreamingOutputCallRequest(
response_type=messages_pb2.COMPRESSABLE,
response_parameters=(
messages_pb2.ResponseParameters(size=1),),
payload=messages_pb2.Payload(body=b'\x00'),
response_status=messages_pb2.EchoStatus(code=code, message=details))
pipe.add(request) # sends the initial request.
# Dropping out of with block closes the pipe
_validate_status_code_and_details(response_iterator, status, details)
def _unimplemented_method(test_service_stub):
response_future = (
test_service_stub.UnimplementedCall.future(empty_pb2.Empty()))
_expect_status_code(response_future, grpc.StatusCode.UNIMPLEMENTED)
def _unimplemented_service(unimplemented_service_stub):
response_future = (
unimplemented_service_stub.UnimplementedCall.future(empty_pb2.Empty()))
_expect_status_code(response_future, grpc.StatusCode.UNIMPLEMENTED)
def _custom_metadata(stub):
initial_metadata_value = "test_initial_metadata_value"
trailing_metadata_value = "\x0a\x0b\x0a\x0b\x0a\x0b"
metadata = (
(_INITIAL_METADATA_KEY, initial_metadata_value),
(_TRAILING_METADATA_KEY, trailing_metadata_value))
def _validate_metadata(response):
initial_metadata = dict(response.initial_metadata())
if initial_metadata[_INITIAL_METADATA_KEY] != initial_metadata_value:
raise ValueError(
'expected initial metadata %s, got %s' % (
initial_metadata_value, initial_metadata[_INITIAL_METADATA_KEY]))
trailing_metadata = dict(response.trailing_metadata())
if trailing_metadata[_TRAILING_METADATA_KEY] != trailing_metadata_value:
raise ValueError(
'expected trailing metadata %s, got %s' % (
trailing_metadata_value, initial_metadata[_TRAILING_METADATA_KEY]))
# Testing with UnaryCall
request = messages_pb2.SimpleRequest(
response_type=messages_pb2.COMPRESSABLE, response_type=messages_pb2.COMPRESSABLE,
response_parameters=( response_size=1,
messages_pb2.ResponseParameters(size=1),), payload=messages_pb2.Payload(body=b'\x00'))
response_status=messages_pb2.EchoStatus(code=code, message=message)) response_future = stub.UnaryCall.future(request, metadata=metadata)
response_iterator = stub.StreamingOutputCall(request) _validate_metadata(response_future)
if response_future.code() != status:
raise ValueError(
'expected code %s, got %s' % (status, response_iterator.code()))
elif response_future.details() != message:
raise ValueError(
'expected message %s, got %s' % (message, response_iterator.details()))
# Testing with FullDuplexCall
with _Pipe() as pipe:
response_iterator = stub.FullDuplexCall(pipe, metadata=metadata)
request = messages_pb2.StreamingOutputCallRequest(
response_type=messages_pb2.COMPRESSABLE,
response_parameters=(
messages_pb2.ResponseParameters(size=1),))
pipe.add(request) # Sends the request
next(response_iterator) # Causes server to send trailing metadata
# Dropping out of the with block closes the pipe
_validate_metadata(response_iterator)
def _compute_engine_creds(stub, args): def _compute_engine_creds(stub, args):
response = _large_unary_common_behavior(stub, True, True, None) response = _large_unary_common_behavior(stub, True, True, None)
@ -381,6 +462,9 @@ class TestCase(enum.Enum):
CANCEL_AFTER_FIRST_RESPONSE = 'cancel_after_first_response' CANCEL_AFTER_FIRST_RESPONSE = 'cancel_after_first_response'
EMPTY_STREAM = 'empty_stream' EMPTY_STREAM = 'empty_stream'
STATUS_CODE_AND_MESSAGE = 'status_code_and_message' STATUS_CODE_AND_MESSAGE = 'status_code_and_message'
UNIMPLEMENTED_METHOD = 'unimplemented_method'
UNIMPLEMENTED_SERVICE = 'unimplemented_service'
CUSTOM_METADATA = "custom_metadata"
COMPUTE_ENGINE_CREDS = 'compute_engine_creds' COMPUTE_ENGINE_CREDS = 'compute_engine_creds'
OAUTH2_AUTH_TOKEN = 'oauth2_auth_token' OAUTH2_AUTH_TOKEN = 'oauth2_auth_token'
JWT_TOKEN_CREDS = 'jwt_token_creds' JWT_TOKEN_CREDS = 'jwt_token_creds'
@ -408,6 +492,12 @@ class TestCase(enum.Enum):
_empty_stream(stub) _empty_stream(stub)
elif self is TestCase.STATUS_CODE_AND_MESSAGE: elif self is TestCase.STATUS_CODE_AND_MESSAGE:
_status_code_and_message(stub) _status_code_and_message(stub)
elif self is TestCase.UNIMPLEMENTED_METHOD:
_unimplemented_method(stub)
elif self is TestCase.UNIMPLEMENTED_SERVICE:
_unimplemented_service(stub)
elif self is TestCase.CUSTOM_METADATA:
_custom_metadata(stub)
elif self is TestCase.COMPUTE_ENGINE_CREDS: elif self is TestCase.COMPUTE_ENGINE_CREDS:
_compute_engine_creds(stub, args) _compute_engine_creds(stub, args)
elif self is TestCase.OAUTH2_AUTH_TOKEN: elif self is TestCase.OAUTH2_AUTH_TOKEN:

@ -37,6 +37,7 @@
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include "src/core/ext/client_channel/resolver_registry.h" #include "src/core/ext/client_channel/resolver_registry.h"
#include "src/core/lib/channel/channel_args.h"
#include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/resolve_address.h"
#include "src/core/lib/iomgr/timer.h" #include "src/core/lib/iomgr/timer.h"
#include "test/core/util/test_config.h" #include "test/core/util/test_config.h"
@ -103,7 +104,7 @@ int main(int argc, char **argv) {
grpc_resolver *resolver = create_resolver("dns:test"); grpc_resolver *resolver = create_resolver("dns:test");
grpc_resolver_result *result = (grpc_resolver_result *)1; grpc_channel_args *result = (grpc_channel_args *)1;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
gpr_event ev1; gpr_event ev1;
@ -122,7 +123,7 @@ int main(int argc, char **argv) {
GPR_ASSERT(wait_loop(30, &ev2)); GPR_ASSERT(wait_loop(30, &ev2));
GPR_ASSERT(result != NULL); GPR_ASSERT(result != NULL);
grpc_resolver_result_unref(&exec_ctx, result); grpc_channel_args_destroy(result);
GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test"); GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test");
grpc_exec_ctx_finish(&exec_ctx); grpc_exec_ctx_finish(&exec_ctx);

@ -38,21 +38,23 @@
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#include "src/core/ext/client_channel/resolver_registry.h" #include "src/core/ext/client_channel/resolver_registry.h"
#include "src/core/ext/client_channel/resolver_result.h" #include "src/core/lib/channel/channel_args.h"
#include "test/core/util/test_config.h" #include "test/core/util/test_config.h"
typedef struct on_resolution_arg { typedef struct on_resolution_arg {
char *expected_server_name; char *expected_server_name;
grpc_resolver_result *resolver_result; grpc_channel_args *resolver_result;
} on_resolution_arg; } on_resolution_arg;
void on_resolution_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { void on_resolution_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
on_resolution_arg *res = arg; on_resolution_arg *res = arg;
const char *server_name = const grpc_arg *channel_arg =
grpc_resolver_result_get_server_name(res->resolver_result); grpc_channel_args_find(res->resolver_result, GRPC_ARG_SERVER_NAME);
GPR_ASSERT(strcmp(res->expected_server_name, server_name) == 0); GPR_ASSERT(channel_arg != NULL);
grpc_resolver_result_unref(exec_ctx, res->resolver_result); GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
GPR_ASSERT(strcmp(res->expected_server_name, channel_arg->value.string) == 0);
grpc_channel_args_destroy(res->resolver_result);
} }
static void test_succeeds(grpc_resolver_factory *factory, const char *string) { static void test_succeeds(grpc_resolver_factory *factory, const char *string) {

@ -42,6 +42,7 @@
#include <grpc/support/port_platform.h> #include <grpc/support/port_platform.h>
#include <grpc/support/string_util.h> #include <grpc/support/string_util.h>
#include "src/core/ext/client_channel/lb_policy_factory.h"
#include "src/core/ext/client_channel/parse_address.h" #include "src/core/ext/client_channel/parse_address.h"
#include "src/core/ext/client_channel/resolver_registry.h" #include "src/core/ext/client_channel/resolver_registry.h"
#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_args.h"
@ -59,7 +60,7 @@ typedef struct {
grpc_resolver base; grpc_resolver base;
// passed-in parameters // passed-in parameters
char* target_name; // the path component of the uri passed in grpc_channel_args* channel_args;
grpc_lb_addresses* addresses; grpc_lb_addresses* addresses;
char* lb_policy_name; char* lb_policy_name;
grpc_method_config_table* method_config_table; grpc_method_config_table* method_config_table;
@ -71,14 +72,14 @@ typedef struct {
// pending next completion, or NULL // pending next completion, or NULL
grpc_closure* next_completion; grpc_closure* next_completion;
// target result address for next completion // target result address for next completion
grpc_resolver_result** target_result; grpc_channel_args** target_result;
} fake_resolver; } fake_resolver;
static void fake_resolver_destroy(grpc_exec_ctx* exec_ctx, grpc_resolver* gr) { static void fake_resolver_destroy(grpc_exec_ctx* exec_ctx, grpc_resolver* gr) {
fake_resolver* r = (fake_resolver*)gr; fake_resolver* r = (fake_resolver*)gr;
gpr_mu_destroy(&r->mu); gpr_mu_destroy(&r->mu);
gpr_free(r->target_name); grpc_channel_args_destroy(r->channel_args);
grpc_lb_addresses_destroy(r->addresses, NULL /* user_data_destroy */); grpc_lb_addresses_destroy(r->addresses);
gpr_free(r->lb_policy_name); gpr_free(r->lb_policy_name);
grpc_method_config_table_unref(r->method_config_table); grpc_method_config_table_unref(r->method_config_table);
gpr_free(r); gpr_free(r);
@ -100,16 +101,21 @@ static void fake_resolver_maybe_finish_next_locked(grpc_exec_ctx* exec_ctx,
fake_resolver* r) { fake_resolver* r) {
if (r->next_completion != NULL && !r->published) { if (r->next_completion != NULL && !r->published) {
r->published = true; r->published = true;
grpc_channel_args* lb_policy_args = NULL; grpc_arg new_args[3];
size_t num_args = 0;
new_args[num_args++] = grpc_lb_addresses_create_channel_arg(r->addresses);
if (r->method_config_table != NULL) { if (r->method_config_table != NULL) {
const grpc_arg arg = new_args[num_args++] =
grpc_method_config_table_create_channel_arg(r->method_config_table); grpc_method_config_table_create_channel_arg(r->method_config_table);
lb_policy_args = grpc_channel_args_copy_and_add(NULL /* src */, &arg, 1);
} }
*r->target_result = grpc_resolver_result_create( if (r->lb_policy_name != NULL) {
r->target_name, new_args[num_args].type = GRPC_ARG_STRING;
grpc_lb_addresses_copy(r->addresses, NULL /* user_data_copy */), new_args[num_args].key = GRPC_ARG_LB_POLICY_NAME;
r->lb_policy_name, lb_policy_args); new_args[num_args].value.string = r->lb_policy_name;
++num_args;
}
*r->target_result =
grpc_channel_args_copy_and_add(r->channel_args, new_args, num_args);
grpc_exec_ctx_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE, NULL); grpc_exec_ctx_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE, NULL);
r->next_completion = NULL; r->next_completion = NULL;
} }
@ -125,7 +131,7 @@ static void fake_resolver_channel_saw_error(grpc_exec_ctx* exec_ctx,
} }
static void fake_resolver_next(grpc_exec_ctx* exec_ctx, grpc_resolver* resolver, static void fake_resolver_next(grpc_exec_ctx* exec_ctx, grpc_resolver* resolver,
grpc_resolver_result** target_result, grpc_channel_args** target_result,
grpc_closure* on_complete) { grpc_closure* on_complete) {
fake_resolver* r = (fake_resolver*)resolver; fake_resolver* r = (fake_resolver*)resolver;
gpr_mu_lock(&r->mu); gpr_mu_lock(&r->mu);
@ -168,7 +174,8 @@ static grpc_resolver* fake_resolver_create(grpc_resolver_factory* factory,
gpr_slice_buffer path_parts; gpr_slice_buffer path_parts;
gpr_slice_buffer_init(&path_parts); gpr_slice_buffer_init(&path_parts);
gpr_slice_split(path_slice, ",", &path_parts); gpr_slice_split(path_slice, ",", &path_parts);
grpc_lb_addresses* addresses = grpc_lb_addresses_create(path_parts.count); grpc_lb_addresses* addresses =
grpc_lb_addresses_create(path_parts.count, NULL /* user_data_vtable */);
bool errors_found = false; bool errors_found = false;
for (size_t i = 0; i < addresses->num_addresses; i++) { for (size_t i = 0; i < addresses->num_addresses; i++) {
grpc_uri ith_uri = *args->uri; grpc_uri ith_uri = *args->uri;
@ -184,7 +191,7 @@ static grpc_resolver* fake_resolver_create(grpc_resolver_factory* factory,
gpr_slice_buffer_destroy(&path_parts); gpr_slice_buffer_destroy(&path_parts);
gpr_slice_unref(path_slice); gpr_slice_unref(path_slice);
if (errors_found) { if (errors_found) {
grpc_lb_addresses_destroy(addresses, NULL /* user_data_destroy */); grpc_lb_addresses_destroy(addresses);
return NULL; return NULL;
} }
// Construct method config table. // Construct method config table.
@ -229,7 +236,12 @@ static grpc_resolver* fake_resolver_create(grpc_resolver_factory* factory,
// Instantiate resolver. // Instantiate resolver.
fake_resolver* r = gpr_malloc(sizeof(fake_resolver)); fake_resolver* r = gpr_malloc(sizeof(fake_resolver));
memset(r, 0, sizeof(*r)); memset(r, 0, sizeof(*r));
r->target_name = gpr_strdup(args->uri->path); grpc_arg server_name_arg;
server_name_arg.type = GRPC_ARG_STRING;
server_name_arg.key = GRPC_ARG_SERVER_NAME;
server_name_arg.value.string = args->uri->path;
r->channel_args =
grpc_channel_args_copy_and_add(args->args, &server_name_arg, 1);
r->addresses = addresses; r->addresses = addresses;
r->lb_policy_name = r->lb_policy_name =
gpr_strdup(grpc_uri_get_query_arg(args->uri, "lb_policy")); gpr_strdup(grpc_uri_get_query_arg(args->uri, "lb_policy"));

@ -636,7 +636,7 @@ TEST_P(End2endTest, SimpleRpcWithCustomeUserAgentPrefix) {
auto iter = trailing_metadata.find("user-agent"); auto iter = trailing_metadata.find("user-agent");
EXPECT_TRUE(iter != trailing_metadata.end()); EXPECT_TRUE(iter != trailing_metadata.end());
grpc::string expected_prefix = user_agent_prefix_ + " grpc-c++/"; grpc::string expected_prefix = user_agent_prefix_ + " grpc-c++/";
EXPECT_TRUE(iter->second.starts_with(expected_prefix)); EXPECT_TRUE(iter->second.starts_with(expected_prefix)) << iter->second;
} }
TEST_P(End2endTest, MultipleRpcsWithVariedBinaryMetadataValue) { TEST_P(End2endTest, MultipleRpcsWithVariedBinaryMetadataValue) {

@ -935,7 +935,6 @@ src/core/ext/client_channel/parse_address.h \
src/core/ext/client_channel/resolver.h \ src/core/ext/client_channel/resolver.h \
src/core/ext/client_channel/resolver_factory.h \ src/core/ext/client_channel/resolver_factory.h \
src/core/ext/client_channel/resolver_registry.h \ src/core/ext/client_channel/resolver_registry.h \
src/core/ext/client_channel/resolver_result.h \
src/core/ext/client_channel/subchannel.h \ src/core/ext/client_channel/subchannel.h \
src/core/ext/client_channel/subchannel_index.h \ src/core/ext/client_channel/subchannel_index.h \
src/core/ext/client_channel/uri_parser.h \ src/core/ext/client_channel/uri_parser.h \
@ -1132,7 +1131,6 @@ src/core/ext/client_channel/parse_address.c \
src/core/ext/client_channel/resolver.c \ src/core/ext/client_channel/resolver.c \
src/core/ext/client_channel/resolver_factory.c \ src/core/ext/client_channel/resolver_factory.c \
src/core/ext/client_channel/resolver_registry.c \ src/core/ext/client_channel/resolver_registry.c \
src/core/ext/client_channel/resolver_result.c \
src/core/ext/client_channel/subchannel.c \ src/core/ext/client_channel/subchannel.c \
src/core/ext/client_channel/subchannel_index.c \ src/core/ext/client_channel/subchannel_index.c \
src/core/ext/client_channel/uri_parser.c \ src/core/ext/client_channel/uri_parser.c \

@ -385,10 +385,10 @@ class PythonLanguage:
'PYTHONPATH': '{}/src/python/gens'.format(DOCKER_WORKDIR_ROOT)} 'PYTHONPATH': '{}/src/python/gens'.format(DOCKER_WORKDIR_ROOT)}
def unimplemented_test_cases(self): def unimplemented_test_cases(self):
return _SKIP_ADVANCED + _SKIP_COMPRESSION return _SKIP_COMPRESSION
def unimplemented_test_cases_server(self): def unimplemented_test_cases_server(self):
return _SKIP_ADVANCED + _SKIP_COMPRESSION return _SKIP_COMPRESSION
def __str__(self): def __str__(self):
return 'python' return 'python'

@ -6820,7 +6820,6 @@
"src/core/ext/client_channel/resolver.h", "src/core/ext/client_channel/resolver.h",
"src/core/ext/client_channel/resolver_factory.h", "src/core/ext/client_channel/resolver_factory.h",
"src/core/ext/client_channel/resolver_registry.h", "src/core/ext/client_channel/resolver_registry.h",
"src/core/ext/client_channel/resolver_result.h",
"src/core/ext/client_channel/subchannel.h", "src/core/ext/client_channel/subchannel.h",
"src/core/ext/client_channel/subchannel_index.h", "src/core/ext/client_channel/subchannel_index.h",
"src/core/ext/client_channel/uri_parser.h" "src/core/ext/client_channel/uri_parser.h"
@ -6856,8 +6855,6 @@
"src/core/ext/client_channel/resolver_factory.h", "src/core/ext/client_channel/resolver_factory.h",
"src/core/ext/client_channel/resolver_registry.c", "src/core/ext/client_channel/resolver_registry.c",
"src/core/ext/client_channel/resolver_registry.h", "src/core/ext/client_channel/resolver_registry.h",
"src/core/ext/client_channel/resolver_result.c",
"src/core/ext/client_channel/resolver_result.h",
"src/core/ext/client_channel/subchannel.c", "src/core/ext/client_channel/subchannel.c",
"src/core/ext/client_channel/subchannel.h", "src/core/ext/client_channel/subchannel.h",
"src/core/ext/client_channel/subchannel_index.c", "src/core/ext/client_channel/subchannel_index.c",

@ -444,7 +444,6 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_factory.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_factory.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_result.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel_index.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel_index.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\uri_parser.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\uri_parser.h" />
@ -816,8 +815,6 @@
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.c"> <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.c">
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_result.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.c"> <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.c">
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel_index.c"> <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel_index.c">

@ -520,9 +520,6 @@
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.c"> <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.c">
<Filter>src\core\ext\client_channel</Filter> <Filter>src\core\ext\client_channel</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_result.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.c"> <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.c">
<Filter>src\core\ext\client_channel</Filter> <Filter>src\core\ext\client_channel</Filter>
</ClCompile> </ClCompile>
@ -1154,9 +1151,6 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.h"> <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.h">
<Filter>src\core\ext\client_channel</Filter> <Filter>src\core\ext\client_channel</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_result.h">
<Filter>src\core\ext\client_channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.h"> <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.h">
<Filter>src\core\ext\client_channel</Filter> <Filter>src\core\ext\client_channel</Filter>
</ClInclude> </ClInclude>

@ -410,7 +410,6 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_factory.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_factory.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_result.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel_index.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel_index.h" />
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\uri_parser.h" /> <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\uri_parser.h" />
@ -734,8 +733,6 @@
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.c"> <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.c">
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_result.c">
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.c"> <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.c">
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel_index.c"> <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel_index.c">

@ -448,9 +448,6 @@
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.c"> <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.c">
<Filter>src\core\ext\client_channel</Filter> <Filter>src\core\ext\client_channel</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_result.c">
<Filter>src\core\ext\client_channel</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.c"> <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.c">
<Filter>src\core\ext\client_channel</Filter> <Filter>src\core\ext\client_channel</Filter>
</ClCompile> </ClCompile>
@ -995,9 +992,6 @@
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.h"> <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.h">
<Filter>src\core\ext\client_channel</Filter> <Filter>src\core\ext\client_channel</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_result.h">
<Filter>src\core\ext\client_channel</Filter>
</ClInclude>
<ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.h"> <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.h">
<Filter>src\core\ext\client_channel</Filter> <Filter>src\core\ext\client_channel</Filter>
</ClInclude> </ClInclude>

Loading…
Cancel
Save