merge conflict resolution

pull/18397/head
Bill Feng 6 years ago
commit 4e046a0956
  1. 1393
      BUILD.gn
  2. 11803
      Makefile
  3. 37
      doc/interop-test-descriptions.md
  4. 561
      grpc.gyp
  5. 20
      include/grpc/impl/codegen/port_platform.h
  6. 15
      include/grpcpp/impl/codegen/client_interceptor.h
  7. 29
      src/boringssl/gen_build_yaml.py
  8. 4
      src/core/ext/filters/client_channel/resolver.cc
  9. 54
      src/core/ext/filters/client_channel/resolver.h
  10. 97
      src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc
  11. 104
      src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc
  12. 88
      src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc
  13. 3
      src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h
  14. 89
      src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc
  15. 4
      src/core/ext/filters/client_channel/resolver_factory.h
  16. 7
      src/core/ext/filters/client_channel/resolver_registry.cc
  17. 8
      src/core/ext/filters/client_channel/resolver_registry.h
  18. 216
      src/core/ext/filters/client_channel/resolving_lb_policy.cc
  19. 14
      src/core/ext/filters/client_channel/resolving_lb_policy.h
  20. 3
      src/core/lib/channel/channel_args.h
  21. 16
      src/core/lib/iomgr/port.h
  22. 10
      src/cpp/client/client_interceptor.cc
  23. 40
      src/csharp/Grpc.Core/Internal/MonoPInvokeCallbackAttribute.cs
  24. 91
      src/csharp/Grpc.Core/Internal/NativeCallbackDispatcher.cs
  25. 3
      src/csharp/Grpc.Core/Internal/NativeExtension.cs
  26. 18
      src/csharp/Grpc.Core/Internal/NativeLogRedirector.cs
  27. 22
      src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs
  28. 17
      src/csharp/Grpc.Core/Internal/NativeMethods.Generated.cs
  29. 36
      src/csharp/ext/grpc_csharp_ext.c
  30. 4
      src/csharp/unitypackage/unitypackage_skeleton/Plugins/Grpc.Core/runtimes/grpc_csharp_ext_dummy_stubs.c
  31. 220
      templates/BUILD.gn.template
  32. 3
      templates/src/csharp/Grpc.Core/Internal/native_methods.include
  33. 111
      test/core/client_channel/resolvers/dns_resolver_connectivity_test.cc
  34. 84
      test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc
  35. 8
      test/core/client_channel/resolvers/dns_resolver_test.cc
  36. 172
      test/core/client_channel/resolvers/fake_resolver_test.cc
  37. 36
      test/core/client_channel/resolvers/sockaddr_resolver_test.cc
  38. 12
      test/cpp/end2end/client_interceptors_end2end_test.cc
  39. 39
      test/cpp/naming/cancel_ares_query_test.cc
  40. 134
      test/cpp/naming/resolver_component_test.cc
  41. 3867
      tools/run_tests/generated/sources_and_headers.json
  42. 1278
      tools/run_tests/generated/tests.json
  43. 132
      tools/run_tests/run_interop_tests.py

1393
BUILD.gn

File diff suppressed because it is too large Load Diff

11803
Makefile

File diff suppressed because it is too large Load Diff

@ -718,6 +718,43 @@ Client asserts:
* received SimpleResponse.username matches the value of
`--default_service_account`
### compute_engine_channel_credentials
Similar to the other auth tests, this test should only be run against prod
servers. Note that this test may only be ran on GCP.
This test verifies unary calls succeed when the client uses
ComputeEngineChannelCredentials. All that is needed by the test environment
is for the client to be running on GCP.
The test uses `--default_service_account` with GCE service account email. This
email must identify the default service account of the GCP VM that the test
is running on.
Server features:
* [UnaryCall][]
* [Echo Authenticated Username][]
Procedure:
1. Client configures the channel to use ComputeEngineChannelCredentials
* Note: the term `ComputeEngineChannelCredentials` within the context
of this test description refers to an API which encapsulates
both "transport credentials" and "call credentials" and which
is capable of transport creds auto-selection (including ALTS).
The exact name of the API may vary per language.
2. Client calls UnaryCall with:
```
{
fill_username: true
}
```
Client asserts:
* call was successful
* received SimpleResponse.username matches the value of
`--default_service_account`
### custom_metadata
This test verifies that custom metadata in either binary or ascii format can be

@ -2058,567 +2058,6 @@
'third_party/boringssl/crypto/test/test_util.cc',
],
},
{
'target_name': 'boringssl_crypto_test_data_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'src/boringssl/crypto_test_data.cc',
],
},
{
'target_name': 'boringssl_asn1_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/asn1/asn1_test.cc',
],
},
{
'target_name': 'boringssl_base64_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/base64/base64_test.cc',
],
},
{
'target_name': 'boringssl_bio_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/bio/bio_test.cc',
],
},
{
'target_name': 'boringssl_buf_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/buf/buf_test.cc',
],
},
{
'target_name': 'boringssl_bytestring_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/bytestring/bytestring_test.cc',
],
},
{
'target_name': 'boringssl_chacha_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/chacha/chacha_test.cc',
],
},
{
'target_name': 'boringssl_aead_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/cipher_extra/aead_test.cc',
],
},
{
'target_name': 'boringssl_cipher_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/cipher_extra/cipher_test.cc',
],
},
{
'target_name': 'boringssl_cmac_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/cmac/cmac_test.cc',
],
},
{
'target_name': 'boringssl_compiler_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/compiler_test.cc',
],
},
{
'target_name': 'boringssl_constant_time_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/constant_time_test.cc',
],
},
{
'target_name': 'boringssl_ed25519_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/curve25519/ed25519_test.cc',
],
},
{
'target_name': 'boringssl_spake25519_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/curve25519/spake25519_test.cc',
],
},
{
'target_name': 'boringssl_x25519_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/curve25519/x25519_test.cc',
],
},
{
'target_name': 'boringssl_dh_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/dh/dh_test.cc',
],
},
{
'target_name': 'boringssl_digest_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/digest_extra/digest_test.cc',
],
},
{
'target_name': 'boringssl_dsa_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/dsa/dsa_test.cc',
],
},
{
'target_name': 'boringssl_ecdh_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/ecdh/ecdh_test.cc',
],
},
{
'target_name': 'boringssl_err_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/err/err_test.cc',
],
},
{
'target_name': 'boringssl_evp_extra_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/evp/evp_extra_test.cc',
],
},
{
'target_name': 'boringssl_evp_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/evp/evp_test.cc',
],
},
{
'target_name': 'boringssl_pbkdf_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/evp/pbkdf_test.cc',
],
},
{
'target_name': 'boringssl_scrypt_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/evp/scrypt_test.cc',
],
},
{
'target_name': 'boringssl_aes_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/fipsmodule/aes/aes_test.cc',
],
},
{
'target_name': 'boringssl_bn_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/fipsmodule/bn/bn_test.cc',
],
},
{
'target_name': 'boringssl_ec_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/fipsmodule/ec/ec_test.cc',
],
},
{
'target_name': 'boringssl_p256-x86_64_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/fipsmodule/ec/p256-x86_64_test.cc',
],
},
{
'target_name': 'boringssl_ecdsa_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/fipsmodule/ecdsa/ecdsa_test.cc',
],
},
{
'target_name': 'boringssl_gcm_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/fipsmodule/modes/gcm_test.cc',
],
},
{
'target_name': 'boringssl_ctrdrbg_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/fipsmodule/rand/ctrdrbg_test.cc',
],
},
{
'target_name': 'boringssl_hkdf_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/hkdf/hkdf_test.cc',
],
},
{
'target_name': 'boringssl_hmac_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/hmac_extra/hmac_test.cc',
],
},
{
'target_name': 'boringssl_lhash_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/lhash/lhash_test.cc',
],
},
{
'target_name': 'boringssl_obj_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/obj/obj_test.cc',
],
},
{
'target_name': 'boringssl_pkcs7_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/pkcs7/pkcs7_test.cc',
],
},
{
'target_name': 'boringssl_pkcs12_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/pkcs8/pkcs12_test.cc',
],
},
{
'target_name': 'boringssl_pkcs8_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/pkcs8/pkcs8_test.cc',
],
},
{
'target_name': 'boringssl_poly1305_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/poly1305/poly1305_test.cc',
],
},
{
'target_name': 'boringssl_pool_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/pool/pool_test.cc',
],
},
{
'target_name': 'boringssl_refcount_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/refcount_test.cc',
],
},
{
'target_name': 'boringssl_rsa_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/rsa_extra/rsa_test.cc',
],
},
{
'target_name': 'boringssl_self_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/self_test.cc',
],
},
{
'target_name': 'boringssl_file_test_gtest_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/test/file_test_gtest.cc',
],
},
{
'target_name': 'boringssl_gtest_main_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/test/gtest_main.cc',
],
},
{
'target_name': 'boringssl_thread_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/thread_test.cc',
],
},
{
'target_name': 'boringssl_x509_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/x509/x509_test.cc',
],
},
{
'target_name': 'boringssl_tab_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/x509v3/tab_test.cc',
],
},
{
'target_name': 'boringssl_v3name_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/crypto/x509v3/v3name_test.cc',
],
},
{
'target_name': 'boringssl_span_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/ssl/span_test.cc',
],
},
{
'target_name': 'boringssl_ssl_test_lib',
'type': 'static_library',
'dependencies': [
'boringssl_test_util',
'boringssl',
],
'sources': [
'third_party/boringssl/ssl/ssl_test.cc',
],
},
{
'target_name': 'benchmark',
'type': 'static_library',

@ -359,6 +359,26 @@
#else /* _LP64 */
#define GPR_ARCH_32 1
#endif /* _LP64 */
#elif defined(__Fuchsia__)
#define GPR_FUCHSIA 1
#define GPR_ARCH_64 1
#define GPR_PLATFORM_STRING "fuchsia"
#include <features.h>
// Specifying musl libc affects wrap_memcpy.c. It causes memmove() to be
// invoked.
#define GPR_MUSL_LIBC_COMPAT 1
#define GPR_CPU_POSIX 1
#define GPR_GCC_ATOMIC 1
#define GPR_PTHREAD_TLS 1
#define GPR_POSIX_LOG 1
#define GPR_POSIX_SYNC 1
#define GPR_POSIX_ENV 1
#define GPR_POSIX_TMPFILE 1
#define GPR_POSIX_SUBPROCESS 1
#define GPR_POSIX_SYNC 1
#define GPR_POSIX_STRING 1
#define GPR_POSIX_TIME 1
#define GPR_GETPID_IN_UNISTD_H 1
#else
#error "Could not auto-detect platform"
#endif

@ -172,17 +172,16 @@ class ClientRpcInfo {
// PLEASE DO NOT USE THIS. ALWAYS PREFER PER CHANNEL INTERCEPTORS OVER A GLOBAL
// INTERCEPTOR. IF USAGE IS ABSOLUTELY NECESSARY, PLEASE READ THE SAFETY NOTES.
// Registers a global client interceptor factory object, which is used for all
// RPCs made in this process. If the argument is nullptr, the global
// interceptor factory is deregistered. The application is responsible for
// maintaining the life of the object while gRPC operations are in progress. It
// is unsafe to try to register/deregister if any gRPC operation is in progress.
// For safety, it is in the best interests of the developer to register the
// global interceptor factory once at the start of the process before any gRPC
// operations have begun. Deregistration is optional since gRPC does not
// maintain any references to the object.
// RPCs made in this process. The application is responsible for maintaining the
// life of the object while gRPC operations are in progress. The global
// interceptor factory should only be registered once at the start of the
// process before any gRPC operations have begun.
void RegisterGlobalClientInterceptorFactory(
ClientInterceptorFactoryInterface* factory);
// For testing purposes only
void TestOnlyResetGlobalClientInterceptorFactory();
} // namespace experimental
} // namespace grpc

@ -48,6 +48,7 @@ class Grpc(object):
yaml = None
def WriteFiles(self, files, asm_outputs):
test_binaries = ['ssl_test', 'crypto_test']
self.yaml = {
'#': 'generated with tools/buildgen/gen_boring_ssl_build_yaml.py',
@ -86,45 +87,28 @@ class Grpc(object):
for f in sorted(files['test_support'])
],
}
] + [
{
'name': 'boringssl_%s_lib' % os.path.splitext(os.path.basename(test))[0],
'build': 'private',
'secure': 'no',
'language': 'c' if os.path.splitext(test)[1] == '.c' else 'c++',
'src': [map_dir(test)],
'vs_proj_dir': 'test/boringssl',
'boringssl': True,
'defaults': 'boringssl',
'deps': [
'boringssl_test_util',
'boringssl',
]
}
for test in list(sorted(set(files['ssl_test'] + files['crypto_test'])))
],
'targets': [
{
'name': 'boringssl_%s' % os.path.splitext(os.path.basename(test))[0],
'name': 'boringssl_%s' % test,
'build': 'test',
'run': False,
'secure': 'no',
'language': 'c++',
'src': ["third_party/boringssl/crypto/test/gtest_main.cc"],
'src': sorted(map_dir(f) for f in files[test]),
'vs_proj_dir': 'test/boringssl',
'boringssl': True,
'defaults': 'boringssl',
'deps': [
'boringssl_%s_lib' % os.path.splitext(os.path.basename(test))[0],
'boringssl_test_util',
'boringssl',
]
}
for test in list(sorted(set(files['ssl_test'] + files['crypto_test'])))
for test in test_binaries
],
'tests': [
{
'name': 'boringssl_%s' % os.path.splitext(os.path.basename(test))[0],
'name': 'boringssl_%s' % test,
'args': [],
'exclude_configs': ['asan', 'ubsan'],
'ci_platforms': ['linux', 'mac', 'posix', 'windows'],
@ -136,9 +120,8 @@ class Grpc(object):
'defaults': 'boringssl',
'cpu_cost': 1.0
}
for test in list(sorted(set(files['ssl_test'] + files['crypto_test'])))
for test in test_binaries
]
}

@ -26,8 +26,10 @@ grpc_core::DebugOnlyTraceFlag grpc_trace_resolver_refcount(false,
namespace grpc_core {
Resolver::Resolver(grpc_combiner* combiner)
Resolver::Resolver(grpc_combiner* combiner,
UniquePtr<ResultHandler> result_handler)
: InternallyRefCounted(&grpc_trace_resolver_refcount),
result_handler_(std::move(result_handler)),
combiner_(GRPC_COMBINER_REF(combiner, "resolver")) {}
Resolver::~Resolver() { GRPC_COMBINER_UNREF(combiner_, "resolver"); }

@ -46,27 +46,34 @@ namespace grpc_core {
/// combiner passed to the constructor.
class Resolver : public InternallyRefCounted<Resolver> {
public:
/// A proxy object used by the resolver to return results to the
/// client channel.
class ResultHandler {
public:
virtual ~ResultHandler() {}
/// Returns a result to the channel.
/// The list of addresses will be in GRPC_ARG_SERVER_ADDRESS_LIST.
/// The service config (if any) will be in GRPC_ARG_SERVICE_CONFIG.
/// Takes ownership of \a result.
// TODO(roth): Change this API so that addresses and service config are
// passed explicitly instead of being in channel args.
virtual void ReturnResult(const grpc_channel_args* result) GRPC_ABSTRACT;
/// Returns a transient error to the channel.
/// If the resolver does not set the GRPC_ERROR_INT_GRPC_STATUS
/// attribute on the error, calls will be failed with status UNKNOWN.
virtual void ReturnError(grpc_error* error) GRPC_ABSTRACT;
GRPC_ABSTRACT_BASE_CLASS
};
// Not copyable nor movable.
Resolver(const Resolver&) = delete;
Resolver& operator=(const Resolver&) = delete;
/// Requests a callback when a new result becomes available.
/// When the new result is available, sets \a *result to the new result
/// and schedules \a on_complete for execution.
/// Upon transient failure, sets \a *result to nullptr and schedules
/// \a on_complete with no error.
/// If resolution is fatally broken, sets \a *result to nullptr and
/// schedules \a on_complete with an error.
/// TODO(roth): When we have time, improve the way this API represents
/// transient failure vs. shutdown.
///
/// Note that the client channel will almost always have a request
/// to \a NextLocked() pending. When it gets the callback, it will
/// process the new result and then immediately make another call to
/// \a NextLocked(). This allows push-based resolvers to provide new
/// data as soon as it becomes available.
virtual void NextLocked(grpc_channel_args** result,
grpc_closure* on_complete) GRPC_ABSTRACT;
/// Starts resolving.
virtual void StartLocked() GRPC_ABSTRACT;
/// Asks the resolver to obtain an updated resolver result, if
/// applicable.
@ -79,8 +86,8 @@ class Resolver : public InternallyRefCounted<Resolver> {
///
/// For push-based implementations, this may be a no-op.
///
/// If this causes new data to become available, then the currently
/// pending call to \a NextLocked() will return the new result.
/// Note: Implementations must not invoke any method on the
/// ResultHandler from within this call.
virtual void RequestReresolutionLocked() {}
/// Resets the re-resolution backoff, if any.
@ -108,16 +115,18 @@ class Resolver : public InternallyRefCounted<Resolver> {
// TODO(roth): Once we have a C++-like interface for combiners, this
// API should change to take a RefCountedPtr<>, so that we always take
// ownership of a new ref.
explicit Resolver(grpc_combiner* combiner);
explicit Resolver(grpc_combiner* combiner,
UniquePtr<ResultHandler> result_handler);
virtual ~Resolver();
/// Shuts down the resolver. If there is a pending call to
/// NextLocked(), the callback will be scheduled with an error.
/// Shuts down the resolver.
virtual void ShutdownLocked() GRPC_ABSTRACT;
grpc_combiner* combiner() const { return combiner_; }
ResultHandler* result_handler() const { return result_handler_.get(); }
private:
static void ShutdownAndUnrefLocked(void* arg, grpc_error* ignored) {
Resolver* resolver = static_cast<Resolver*>(arg);
@ -125,6 +134,7 @@ class Resolver : public InternallyRefCounted<Resolver> {
resolver->Unref();
}
UniquePtr<ResultHandler> result_handler_;
grpc_combiner* combiner_;
};

@ -60,10 +60,9 @@ const char kDefaultPort[] = "https";
class AresDnsResolver : public Resolver {
public:
explicit AresDnsResolver(const ResolverArgs& args);
explicit AresDnsResolver(ResolverArgs args);
void NextLocked(grpc_channel_args** result,
grpc_closure* on_complete) override;
void StartLocked() override;
void RequestReresolutionLocked() override;
@ -76,7 +75,6 @@ class AresDnsResolver : public Resolver {
void MaybeStartResolvingLocked();
void StartResolvingLocked();
void MaybeFinishNextLocked();
static void OnNextResolutionLocked(void* arg, grpc_error* error);
static void OnResolvedLocked(void* arg, grpc_error* error);
@ -98,16 +96,6 @@ class AresDnsResolver : public Resolver {
bool resolving_ = false;
/// the pending resolving request
grpc_ares_request* pending_request_ = nullptr;
/// which version of the result have we published?
int published_version_ = 0;
/// which version of the result is current?
int resolved_version_ = 0;
/// pending next completion, or NULL
grpc_closure* next_completion_ = nullptr;
/// target result address for next completion
grpc_channel_args** target_result_ = nullptr;
/// current (fully resolved) result
grpc_channel_args* resolved_result_ = nullptr;
/// next resolution timer
bool have_next_resolution_timer_ = false;
grpc_timer next_resolution_timer_;
@ -129,8 +117,8 @@ class AresDnsResolver : public Resolver {
bool enable_srv_queries_;
};
AresDnsResolver::AresDnsResolver(const ResolverArgs& args)
: Resolver(args.combiner),
AresDnsResolver::AresDnsResolver(ResolverArgs args)
: Resolver(args.combiner, std::move(args.result_handler)),
backoff_(
BackOff::Options()
.set_initial_backoff(GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS *
@ -177,27 +165,16 @@ AresDnsResolver::AresDnsResolver(const ResolverArgs& args)
AresDnsResolver::~AresDnsResolver() {
GRPC_CARES_TRACE_LOG("resolver:%p destroying AresDnsResolver", this);
if (resolved_result_ != nullptr) {
grpc_channel_args_destroy(resolved_result_);
}
grpc_pollset_set_destroy(interested_parties_);
gpr_free(dns_server_);
gpr_free(name_to_resolve_);
grpc_channel_args_destroy(channel_args_);
}
void AresDnsResolver::NextLocked(grpc_channel_args** target_result,
grpc_closure* on_complete) {
GRPC_CARES_TRACE_LOG("resolver:%p AresDnsResolver::NextLocked() is called.",
void AresDnsResolver::StartLocked() {
GRPC_CARES_TRACE_LOG("resolver:%p AresDnsResolver::StartLocked() is called.",
this);
GPR_ASSERT(next_completion_ == nullptr);
next_completion_ = on_complete;
target_result_ = target_result;
if (resolved_version_ == 0 && !resolving_) {
MaybeStartResolvingLocked();
} else {
MaybeFinishNextLocked();
}
MaybeStartResolvingLocked();
}
void AresDnsResolver::RequestReresolutionLocked() {
@ -221,12 +198,6 @@ void AresDnsResolver::ShutdownLocked() {
if (pending_request_ != nullptr) {
grpc_cancel_ares_request_locked(pending_request_);
}
if (next_completion_ != nullptr) {
*target_result_ = nullptr;
GRPC_CLOSURE_SCHED(next_completion_, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Resolver Shutdown"));
next_completion_ = nullptr;
}
}
void AresDnsResolver::OnNextResolutionLocked(void* arg, grpc_error* error) {
@ -319,11 +290,14 @@ char* ChooseServiceConfig(char* service_config_choice_json) {
void AresDnsResolver::OnResolvedLocked(void* arg, grpc_error* error) {
AresDnsResolver* r = static_cast<AresDnsResolver*>(arg);
grpc_channel_args* result = nullptr;
GPR_ASSERT(r->resolving_);
r->resolving_ = false;
gpr_free(r->pending_request_);
r->pending_request_ = nullptr;
if (r->shutdown_initiated_) {
r->Unref(DEBUG_LOCATION, "OnResolvedLocked() shutdown");
return;
}
if (r->addresses_ != nullptr) {
static const char* args_to_remove[1];
size_t num_args_to_remove = 0;
@ -343,17 +317,22 @@ void AresDnsResolver::OnResolvedLocked(void* arg, grpc_error* error) {
(char*)GRPC_ARG_SERVICE_CONFIG, service_config_string);
}
}
result = grpc_channel_args_copy_and_add_and_remove(
r->result_handler()->ReturnResult(grpc_channel_args_copy_and_add_and_remove(
r->channel_args_, args_to_remove, num_args_to_remove, args_to_add,
num_args_to_add);
num_args_to_add));
gpr_free(service_config_string);
r->addresses_.reset();
// Reset backoff state so that we start from the beginning when the
// next request gets triggered.
r->backoff_.Reset();
} else if (!r->shutdown_initiated_) {
const char* msg = grpc_error_string(error);
GRPC_CARES_TRACE_LOG("resolver:%p dns resolution failed: %s", r, msg);
} else {
GRPC_CARES_TRACE_LOG("resolver:%p dns resolution failed: %s", r,
grpc_error_string(error));
r->result_handler()->ReturnError(grpc_error_set_int(
GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
"DNS resolution failed", &error, 1),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE));
// Set retry timer.
grpc_millis next_try = r->backoff_.NextAttemptTime();
grpc_millis timeout = next_try - ExecCtx::Get()->Now();
GRPC_CARES_TRACE_LOG("resolver:%p dns resolution failed (will retry): %s",
@ -363,8 +342,7 @@ void AresDnsResolver::OnResolvedLocked(void* arg, grpc_error* error) {
// TODO(roth): We currently deal with this ref manually. Once the
// new closure API is done, find a way to track this ref with the timer
// callback as part of the type system.
RefCountedPtr<Resolver> self = r->Ref(DEBUG_LOCATION, "retry-timer");
self.release();
r->Ref(DEBUG_LOCATION, "retry-timer").release();
if (timeout > 0) {
GRPC_CARES_TRACE_LOG("resolver:%p retrying in %" PRId64 " milliseconds",
r, timeout);
@ -374,12 +352,6 @@ void AresDnsResolver::OnResolvedLocked(void* arg, grpc_error* error) {
grpc_timer_init(&r->next_resolution_timer_, next_try,
&r->on_next_resolution_);
}
if (r->resolved_result_ != nullptr) {
grpc_channel_args_destroy(r->resolved_result_);
}
r->resolved_result_ = result;
++r->resolved_version_;
r->MaybeFinishNextLocked();
r->Unref(DEBUG_LOCATION, "dns-resolving");
}
@ -403,9 +375,7 @@ void AresDnsResolver::MaybeStartResolvingLocked() {
// TODO(roth): We currently deal with this ref manually. Once the
// new closure API is done, find a way to track this ref with the timer
// callback as part of the type system.
RefCountedPtr<Resolver> self =
Ref(DEBUG_LOCATION, "next_resolution_timer_cooldown");
self.release();
Ref(DEBUG_LOCATION, "next_resolution_timer_cooldown").release();
grpc_timer_init(&next_resolution_timer_, ms_until_next_resolution,
&on_next_resolution_);
return;
@ -418,8 +388,7 @@ void AresDnsResolver::StartResolvingLocked() {
// TODO(roth): We currently deal with this ref manually. Once the
// new closure API is done, find a way to track this ref with the timer
// callback as part of the type system.
RefCountedPtr<Resolver> self = Ref(DEBUG_LOCATION, "dns-resolving");
self.release();
Ref(DEBUG_LOCATION, "dns-resolving").release();
GPR_ASSERT(!resolving_);
resolving_ = true;
service_config_json_ = nullptr;
@ -433,28 +402,14 @@ void AresDnsResolver::StartResolvingLocked() {
this, pending_request_);
}
void AresDnsResolver::MaybeFinishNextLocked() {
if (next_completion_ != nullptr && resolved_version_ != published_version_) {
*target_result_ = resolved_result_ == nullptr
? nullptr
: grpc_channel_args_copy(resolved_result_);
GRPC_CARES_TRACE_LOG("resolver:%p AresDnsResolver::MaybeFinishNextLocked()",
this);
GRPC_CLOSURE_SCHED(next_completion_, GRPC_ERROR_NONE);
next_completion_ = nullptr;
published_version_ = resolved_version_;
}
}
//
// Factory
//
class AresDnsResolverFactory : public ResolverFactory {
public:
OrphanablePtr<Resolver> CreateResolver(
const ResolverArgs& args) const override {
return OrphanablePtr<Resolver>(New<AresDnsResolver>(args));
OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
return OrphanablePtr<Resolver>(New<AresDnsResolver>(std::move(args)));
}
const char* scheme() const override { return "dns"; }

@ -51,10 +51,9 @@ const char kDefaultPort[] = "https";
class NativeDnsResolver : public Resolver {
public:
explicit NativeDnsResolver(const ResolverArgs& args);
explicit NativeDnsResolver(ResolverArgs args);
void NextLocked(grpc_channel_args** result,
grpc_closure* on_complete) override;
void StartLocked() override;
void RequestReresolutionLocked() override;
@ -67,7 +66,6 @@ class NativeDnsResolver : public Resolver {
void MaybeStartResolvingLocked();
void StartResolvingLocked();
void MaybeFinishNextLocked();
static void OnNextResolutionLocked(void* arg, grpc_error* error);
static void OnResolvedLocked(void* arg, grpc_error* error);
@ -78,19 +76,11 @@ class NativeDnsResolver : public Resolver {
grpc_channel_args* channel_args_ = nullptr;
/// pollset_set to drive the name resolution process
grpc_pollset_set* interested_parties_ = nullptr;
/// are we shutting down?
bool shutdown_ = false;
/// are we currently resolving?
bool resolving_ = false;
grpc_closure on_resolved_;
/// which version of the result have we published?
int published_version_ = 0;
/// which version of the result is current?
int resolved_version_ = 0;
/// pending next completion, or nullptr
grpc_closure* next_completion_ = nullptr;
/// target result address for next completion
grpc_channel_args** target_result_ = nullptr;
/// current (fully resolved) result
grpc_channel_args* resolved_result_ = nullptr;
/// next resolution timer
bool have_next_resolution_timer_ = false;
grpc_timer next_resolution_timer_;
@ -105,8 +95,8 @@ class NativeDnsResolver : public Resolver {
grpc_resolved_addresses* addresses_ = nullptr;
};
NativeDnsResolver::NativeDnsResolver(const ResolverArgs& args)
: Resolver(args.combiner),
NativeDnsResolver::NativeDnsResolver(ResolverArgs args)
: Resolver(args.combiner, std::move(args.result_handler)),
backoff_(
BackOff::Options()
.set_initial_backoff(GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS *
@ -134,25 +124,12 @@ NativeDnsResolver::NativeDnsResolver(const ResolverArgs& args)
}
NativeDnsResolver::~NativeDnsResolver() {
if (resolved_result_ != nullptr) {
grpc_channel_args_destroy(resolved_result_);
}
grpc_channel_args_destroy(channel_args_);
grpc_pollset_set_destroy(interested_parties_);
gpr_free(name_to_resolve_);
grpc_channel_args_destroy(channel_args_);
}
void NativeDnsResolver::NextLocked(grpc_channel_args** result,
grpc_closure* on_complete) {
GPR_ASSERT(next_completion_ == nullptr);
next_completion_ = on_complete;
target_result_ = result;
if (resolved_version_ == 0 && !resolving_) {
MaybeStartResolvingLocked();
} else {
MaybeFinishNextLocked();
}
}
void NativeDnsResolver::StartLocked() { MaybeStartResolvingLocked(); }
void NativeDnsResolver::RequestReresolutionLocked() {
if (!resolving_) {
@ -168,15 +145,10 @@ void NativeDnsResolver::ResetBackoffLocked() {
}
void NativeDnsResolver::ShutdownLocked() {
shutdown_ = true;
if (have_next_resolution_timer_) {
grpc_timer_cancel(&next_resolution_timer_);
}
if (next_completion_ != nullptr) {
*target_result_ = nullptr;
GRPC_CLOSURE_SCHED(next_completion_, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Resolver Shutdown"));
next_completion_ = nullptr;
}
}
void NativeDnsResolver::OnNextResolutionLocked(void* arg, grpc_error* error) {
@ -190,38 +162,42 @@ void NativeDnsResolver::OnNextResolutionLocked(void* arg, grpc_error* error) {
void NativeDnsResolver::OnResolvedLocked(void* arg, grpc_error* error) {
NativeDnsResolver* r = static_cast<NativeDnsResolver*>(arg);
grpc_channel_args* result = nullptr;
GPR_ASSERT(r->resolving_);
r->resolving_ = false;
GRPC_ERROR_REF(error);
error =
grpc_error_set_str(error, GRPC_ERROR_STR_TARGET_ADDRESS,
grpc_slice_from_copied_string(r->name_to_resolve_));
if (r->shutdown_) {
r->Unref(DEBUG_LOCATION, "dns-resolving");
return;
}
if (r->addresses_ != nullptr) {
ServerAddressList addresses;
for (size_t i = 0; i < r->addresses_->naddrs; ++i) {
addresses.emplace_back(&r->addresses_->addrs[i].addr,
r->addresses_->addrs[i].len, nullptr /* args */);
}
grpc_arg new_arg = CreateServerAddressListChannelArg(&addresses);
result = grpc_channel_args_copy_and_add(r->channel_args_, &new_arg, 1);
grpc_resolved_addresses_destroy(r->addresses_);
grpc_arg new_arg = CreateServerAddressListChannelArg(&addresses);
r->result_handler()->ReturnResult(
grpc_channel_args_copy_and_add(r->channel_args_, &new_arg, 1));
// Reset backoff state so that we start from the beginning when the
// next request gets triggered.
r->backoff_.Reset();
} else {
grpc_millis next_try = r->backoff_.NextAttemptTime();
grpc_millis timeout = next_try - ExecCtx::Get()->Now();
gpr_log(GPR_INFO, "dns resolution failed (will retry): %s",
grpc_error_string(error));
// Return transient error.
r->result_handler()->ReturnError(grpc_error_set_int(
GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
"DNS resolution failed", &error, 1),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE));
// Set up for retry.
grpc_millis next_try = r->backoff_.NextAttemptTime();
grpc_millis timeout = next_try - ExecCtx::Get()->Now();
GPR_ASSERT(!r->have_next_resolution_timer_);
r->have_next_resolution_timer_ = true;
// TODO(roth): We currently deal with this ref manually. Once the
// new closure API is done, find a way to track this ref with the timer
// callback as part of the type system.
RefCountedPtr<Resolver> self =
r->Ref(DEBUG_LOCATION, "next_resolution_timer");
self.release();
r->Ref(DEBUG_LOCATION, "next_resolution_timer").release();
if (timeout > 0) {
gpr_log(GPR_DEBUG, "retrying in %" PRId64 " milliseconds", timeout);
} else {
@ -230,13 +206,6 @@ void NativeDnsResolver::OnResolvedLocked(void* arg, grpc_error* error) {
grpc_timer_init(&r->next_resolution_timer_, next_try,
&r->on_next_resolution_);
}
if (r->resolved_result_ != nullptr) {
grpc_channel_args_destroy(r->resolved_result_);
}
r->resolved_result_ = result;
++r->resolved_version_;
r->MaybeFinishNextLocked();
GRPC_ERROR_UNREF(error);
r->Unref(DEBUG_LOCATION, "dns-resolving");
}
@ -260,9 +229,7 @@ void NativeDnsResolver::MaybeStartResolvingLocked() {
// TODO(roth): We currently deal with this ref manually. Once the
// new closure API is done, find a way to track this ref with the timer
// callback as part of the type system.
RefCountedPtr<Resolver> self =
Ref(DEBUG_LOCATION, "next_resolution_timer_cooldown");
self.release();
Ref(DEBUG_LOCATION, "next_resolution_timer_cooldown").release();
grpc_timer_init(&next_resolution_timer_, ms_until_next_resolution,
&on_next_resolution_);
return;
@ -276,8 +243,7 @@ void NativeDnsResolver::StartResolvingLocked() {
// TODO(roth): We currently deal with this ref manually. Once the
// new closure API is done, find a way to track this ref with the timer
// callback as part of the type system.
RefCountedPtr<Resolver> self = Ref(DEBUG_LOCATION, "dns-resolving");
self.release();
Ref(DEBUG_LOCATION, "dns-resolving").release();
GPR_ASSERT(!resolving_);
resolving_ = true;
addresses_ = nullptr;
@ -286,30 +252,18 @@ void NativeDnsResolver::StartResolvingLocked() {
last_resolution_timestamp_ = grpc_core::ExecCtx::Get()->Now();
}
void NativeDnsResolver::MaybeFinishNextLocked() {
if (next_completion_ != nullptr && resolved_version_ != published_version_) {
*target_result_ = resolved_result_ == nullptr
? nullptr
: grpc_channel_args_copy(resolved_result_);
GRPC_CLOSURE_SCHED(next_completion_, GRPC_ERROR_NONE);
next_completion_ = nullptr;
published_version_ = resolved_version_;
}
}
//
// Factory
//
class NativeDnsResolverFactory : public ResolverFactory {
public:
OrphanablePtr<Resolver> CreateResolver(
const ResolverArgs& args) const override {
OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
if (GPR_UNLIKELY(0 != strcmp(args.uri->authority, ""))) {
gpr_log(GPR_ERROR, "authority based dns uri's not supported");
return OrphanablePtr<Resolver>(nullptr);
}
return OrphanablePtr<Resolver>(New<NativeDnsResolver>(args));
return OrphanablePtr<Resolver>(New<NativeDnsResolver>(std::move(args)));
}
const char* scheme() const override { return "dns"; }

@ -50,10 +50,9 @@ namespace grpc_core {
// FakeResolverResponseGenerator.
class FakeResolver : public Resolver {
public:
explicit FakeResolver(const ResolverArgs& args);
explicit FakeResolver(ResolverArgs args);
void NextLocked(grpc_channel_args** result,
grpc_closure* on_complete) override;
void StartLocked() override;
void RequestReresolutionLocked() override;
@ -62,27 +61,32 @@ class FakeResolver : public Resolver {
virtual ~FakeResolver();
void MaybeFinishNextLocked();
void ShutdownLocked() override { active_ = false; }
void ShutdownLocked() override;
void MaybeSendResultLocked();
static void ReturnReresolutionResult(void* arg, grpc_error* error);
// passed-in parameters
grpc_channel_args* channel_args_ = nullptr;
// If not NULL, the next set of resolution results to be returned to
// NextLocked()'s closure.
// If not NULL, the next set of resolution results to be returned.
grpc_channel_args* next_results_ = nullptr;
// Results to use for the pretended re-resolution in
// RequestReresolutionLocked().
grpc_channel_args* reresolution_results_ = nullptr;
// pending next completion, or NULL
grpc_closure* next_completion_ = nullptr;
// target result address for next completion
grpc_channel_args** target_result_ = nullptr;
// True between the calls to StartLocked() ShutdownLocked().
bool active_ = false;
// if true, return failure
bool return_failure_ = false;
// pending re-resolution
grpc_closure reresolution_closure_;
bool reresolution_closure_pending_ = false;
};
FakeResolver::FakeResolver(const ResolverArgs& args) : Resolver(args.combiner) {
FakeResolver::FakeResolver(ResolverArgs args)
: Resolver(args.combiner, std::move(args.result_handler)) {
GRPC_CLOSURE_INIT(&reresolution_closure_, ReturnReresolutionResult, this,
grpc_combiner_scheduler(combiner()));
channel_args_ = grpc_channel_args_copy(args.args);
FakeResolverResponseGenerator* response_generator =
FakeResolverResponseGenerator::GetFromArgs(args.args);
@ -102,46 +106,51 @@ FakeResolver::~FakeResolver() {
grpc_channel_args_destroy(channel_args_);
}
void FakeResolver::NextLocked(grpc_channel_args** target_result,
grpc_closure* on_complete) {
GPR_ASSERT(next_completion_ == nullptr);
next_completion_ = on_complete;
target_result_ = target_result;
MaybeFinishNextLocked();
void FakeResolver::StartLocked() {
active_ = true;
MaybeSendResultLocked();
}
void FakeResolver::RequestReresolutionLocked() {
if (reresolution_results_ != nullptr || return_failure_) {
grpc_channel_args_destroy(next_results_);
next_results_ = grpc_channel_args_copy(reresolution_results_);
MaybeFinishNextLocked();
// Return the result in a different closure, so that we don't call
// back into the LB policy while it's still processing the previous
// update.
if (!reresolution_closure_pending_) {
reresolution_closure_pending_ = true;
Ref().release(); // ref held by closure
GRPC_CLOSURE_SCHED(&reresolution_closure_, GRPC_ERROR_NONE);
}
}
}
void FakeResolver::MaybeFinishNextLocked() {
if (next_completion_ != nullptr &&
(next_results_ != nullptr || return_failure_)) {
void FakeResolver::MaybeSendResultLocked() {
if (!active_) return;
if (return_failure_) {
// TODO(roth): Change resolver result generator to be able to inject
// the error to be returned.
result_handler()->ReturnError(grpc_error_set_int(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("Resolver transient failure"),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE));
return_failure_ = false;
} else if (next_results_ != nullptr) {
// When both next_results_ and channel_args_ contain an arg with the same
// name, only the one in next_results_ will be kept since next_results_ is
// before channel_args_.
*target_result_ =
return_failure_ ? nullptr
: grpc_channel_args_union(next_results_, channel_args_);
result_handler()->ReturnResult(
grpc_channel_args_union(next_results_, channel_args_));
grpc_channel_args_destroy(next_results_);
next_results_ = nullptr;
GRPC_CLOSURE_SCHED(next_completion_, GRPC_ERROR_NONE);
next_completion_ = nullptr;
return_failure_ = false;
}
}
void FakeResolver::ShutdownLocked() {
if (next_completion_ != nullptr) {
*target_result_ = nullptr;
GRPC_CLOSURE_SCHED(next_completion_, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Resolver Shutdown"));
next_completion_ = nullptr;
}
void FakeResolver::ReturnReresolutionResult(void* arg, grpc_error* error) {
FakeResolver* self = static_cast<FakeResolver*>(arg);
self->reresolution_closure_pending_ = false;
self->MaybeSendResultLocked();
self->Unref();
}
//
@ -161,7 +170,7 @@ void FakeResolverResponseGenerator::SetResponseLocked(void* arg,
FakeResolver* resolver = closure_arg->generator->resolver_;
grpc_channel_args_destroy(resolver->next_results_);
resolver->next_results_ = closure_arg->response;
resolver->MaybeFinishNextLocked();
resolver->MaybeSendResultLocked();
Delete(closure_arg);
}
@ -210,7 +219,7 @@ void FakeResolverResponseGenerator::SetFailureLocked(void* arg,
SetResponseClosureArg* closure_arg = static_cast<SetResponseClosureArg*>(arg);
FakeResolver* resolver = closure_arg->generator->resolver_;
resolver->return_failure_ = true;
if (closure_arg->immediate) resolver->MaybeFinishNextLocked();
if (closure_arg->immediate) resolver->MaybeSendResultLocked();
Delete(closure_arg);
}
@ -290,9 +299,8 @@ namespace {
class FakeResolverFactory : public ResolverFactory {
public:
OrphanablePtr<Resolver> CreateResolver(
const ResolverArgs& args) const override {
return OrphanablePtr<Resolver>(New<FakeResolver>(args));
OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
return OrphanablePtr<Resolver>(New<FakeResolver>(std::move(args)));
}
const char* scheme() const override { return "fake"; }

@ -58,8 +58,7 @@ class FakeResolverResponseGenerator
// is called.
void SetReresolutionResponse(grpc_channel_args* response);
// Tells the resolver to return a transient failure (signalled by
// returning a null result with no error).
// Tells the resolver to return a transient failure.
void SetFailure();
// Same as SetFailure(), but instead of returning the error

@ -45,66 +45,29 @@ namespace {
class SockaddrResolver : public Resolver {
public:
/// Takes ownership of \a addresses.
SockaddrResolver(const ResolverArgs& args,
UniquePtr<ServerAddressList> addresses);
explicit SockaddrResolver(ResolverArgs args);
~SockaddrResolver() override;
void NextLocked(grpc_channel_args** result,
grpc_closure* on_complete) override;
void StartLocked() override;
void ShutdownLocked() override;
void ShutdownLocked() override {}
private:
virtual ~SockaddrResolver();
void MaybeFinishNextLocked();
/// the addresses that we've "resolved"
UniquePtr<ServerAddressList> addresses_;
/// channel args
grpc_channel_args* channel_args_ = nullptr;
/// have we published?
bool published_ = false;
/// pending next completion, or NULL
grpc_closure* next_completion_ = nullptr;
/// target result address for next completion
grpc_channel_args** target_result_ = nullptr;
const grpc_channel_args* channel_args_ = nullptr;
};
SockaddrResolver::SockaddrResolver(const ResolverArgs& args,
UniquePtr<ServerAddressList> addresses)
: Resolver(args.combiner),
addresses_(std::move(addresses)),
channel_args_(grpc_channel_args_copy(args.args)) {}
SockaddrResolver::SockaddrResolver(ResolverArgs args)
: Resolver(args.combiner, std::move(args.result_handler)),
channel_args_(args.args) {}
SockaddrResolver::~SockaddrResolver() {
grpc_channel_args_destroy(channel_args_);
}
void SockaddrResolver::NextLocked(grpc_channel_args** target_result,
grpc_closure* on_complete) {
GPR_ASSERT(!next_completion_);
next_completion_ = on_complete;
target_result_ = target_result;
MaybeFinishNextLocked();
}
void SockaddrResolver::ShutdownLocked() {
if (next_completion_ != nullptr) {
*target_result_ = nullptr;
GRPC_CLOSURE_SCHED(next_completion_, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
"Resolver Shutdown"));
next_completion_ = nullptr;
}
}
void SockaddrResolver::MaybeFinishNextLocked() {
if (next_completion_ != nullptr && !published_) {
published_ = true;
grpc_arg arg = CreateServerAddressListChannelArg(addresses_.get());
*target_result_ = grpc_channel_args_copy_and_add(channel_args_, &arg, 1);
GRPC_CLOSURE_SCHED(next_completion_, GRPC_ERROR_NONE);
next_completion_ = nullptr;
}
void SockaddrResolver::StartLocked() {
result_handler()->ReturnResult(channel_args_);
channel_args_ = nullptr;
}
//
@ -114,7 +77,7 @@ void SockaddrResolver::MaybeFinishNextLocked() {
void DoNothing(void* ignored) {}
OrphanablePtr<Resolver> CreateSockaddrResolver(
const ResolverArgs& args,
ResolverArgs args,
bool parse(const grpc_uri* uri, grpc_resolved_address* dst)) {
if (0 != strcmp(args.uri->authority, "")) {
gpr_log(GPR_ERROR, "authority-based URIs not supported by the %s scheme",
@ -127,7 +90,7 @@ OrphanablePtr<Resolver> CreateSockaddrResolver(
grpc_slice_buffer path_parts;
grpc_slice_buffer_init(&path_parts);
grpc_slice_split(path_slice, ",", &path_parts);
auto addresses = MakeUnique<ServerAddressList>();
ServerAddressList addresses;
bool errors_found = false;
for (size_t i = 0; i < path_parts.count; i++) {
grpc_uri ith_uri = *args.uri;
@ -135,26 +98,28 @@ OrphanablePtr<Resolver> CreateSockaddrResolver(
ith_uri.path = part_str.get();
grpc_resolved_address addr;
if (!parse(&ith_uri, &addr)) {
errors_found = true; /* GPR_TRUE */
errors_found = true;
break;
}
addresses->emplace_back(addr, nullptr /* args */);
addresses.emplace_back(addr, nullptr /* args */);
}
grpc_slice_buffer_destroy_internal(&path_parts);
grpc_slice_unref_internal(path_slice);
if (errors_found) {
return OrphanablePtr<Resolver>(nullptr);
}
// Add addresses to channel args.
// Note: SockaddrResolver takes ownership of channel args.
grpc_arg arg = CreateServerAddressListChannelArg(&addresses);
args.args = grpc_channel_args_copy_and_add(args.args, &arg, 1);
// Instantiate resolver.
return OrphanablePtr<Resolver>(
New<SockaddrResolver>(args, std::move(addresses)));
return OrphanablePtr<Resolver>(New<SockaddrResolver>(std::move(args)));
}
class IPv4ResolverFactory : public ResolverFactory {
public:
OrphanablePtr<Resolver> CreateResolver(
const ResolverArgs& args) const override {
return CreateSockaddrResolver(args, grpc_parse_ipv4);
OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
return CreateSockaddrResolver(std::move(args), grpc_parse_ipv4);
}
const char* scheme() const override { return "ipv4"; }
@ -162,9 +127,8 @@ class IPv4ResolverFactory : public ResolverFactory {
class IPv6ResolverFactory : public ResolverFactory {
public:
OrphanablePtr<Resolver> CreateResolver(
const ResolverArgs& args) const override {
return CreateSockaddrResolver(args, grpc_parse_ipv6);
OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
return CreateSockaddrResolver(std::move(args), grpc_parse_ipv6);
}
const char* scheme() const override { return "ipv6"; }
@ -173,9 +137,8 @@ class IPv6ResolverFactory : public ResolverFactory {
#ifdef GRPC_HAVE_UNIX_SOCKET
class UnixResolverFactory : public ResolverFactory {
public:
OrphanablePtr<Resolver> CreateResolver(
const ResolverArgs& args) const override {
return CreateSockaddrResolver(args, grpc_parse_unix);
OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override {
return CreateSockaddrResolver(std::move(args), grpc_parse_unix);
}
UniquePtr<char> GetDefaultAuthority(grpc_uri* uri) const override {

@ -41,12 +41,14 @@ struct ResolverArgs {
grpc_pollset_set* pollset_set = nullptr;
/// The combiner under which all resolver calls will be run.
grpc_combiner* combiner = nullptr;
/// The result handler to be used by the resolver.
UniquePtr<Resolver::ResultHandler> result_handler;
};
class ResolverFactory {
public:
/// Returns a new resolver instance.
virtual OrphanablePtr<Resolver> CreateResolver(const ResolverArgs& args) const
virtual OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const
GRPC_ABSTRACT;
/// Returns a string representing the default authority to use for this

@ -134,7 +134,8 @@ ResolverFactory* ResolverRegistry::LookupResolverFactory(const char* scheme) {
OrphanablePtr<Resolver> ResolverRegistry::CreateResolver(
const char* target, const grpc_channel_args* args,
grpc_pollset_set* pollset_set, grpc_combiner* combiner) {
grpc_pollset_set* pollset_set, grpc_combiner* combiner,
UniquePtr<Resolver::ResultHandler> result_handler) {
GPR_ASSERT(g_state != nullptr);
grpc_uri* uri = nullptr;
char* canonical_target = nullptr;
@ -145,8 +146,10 @@ OrphanablePtr<Resolver> ResolverRegistry::CreateResolver(
resolver_args.args = args;
resolver_args.pollset_set = pollset_set;
resolver_args.combiner = combiner;
resolver_args.result_handler = std::move(result_handler);
OrphanablePtr<Resolver> resolver =
factory == nullptr ? nullptr : factory->CreateResolver(resolver_args);
factory == nullptr ? nullptr
: factory->CreateResolver(std::move(resolver_args));
grpc_uri_destroy(uri);
gpr_free(canonical_target);
return resolver;

@ -62,10 +62,10 @@ class ResolverRegistry {
/// \a args are the channel args to be included in resolver results.
/// \a pollset_set is used to drive I/O in the name resolution process.
/// \a combiner is the combiner under which all resolver calls will be run.
static OrphanablePtr<Resolver> CreateResolver(const char* target,
const grpc_channel_args* args,
grpc_pollset_set* pollset_set,
grpc_combiner* combiner);
static OrphanablePtr<Resolver> CreateResolver(
const char* target, const grpc_channel_args* args,
grpc_pollset_set* pollset_set, grpc_combiner* combiner,
UniquePtr<Resolver::ResultHandler> result_handler);
/// Returns the default authority to pass from a client for \a target.
static UniquePtr<char> GetDefaultAuthority(const char* target);

@ -65,6 +65,36 @@
namespace grpc_core {
//
// ResolvingLoadBalancingPolicy::ResolverResultHandler
//
class ResolvingLoadBalancingPolicy::ResolverResultHandler
: public Resolver::ResultHandler {
public:
explicit ResolverResultHandler(
RefCountedPtr<ResolvingLoadBalancingPolicy> parent)
: parent_(std::move(parent)) {}
~ResolverResultHandler() {
if (parent_->tracer_->enabled()) {
gpr_log(GPR_INFO, "resolving_lb=%p: resolver shutdown complete",
parent_.get());
}
}
void ReturnResult(const grpc_channel_args* result) override {
parent_->OnResolverResultChangedLocked(result);
}
void ReturnError(grpc_error* error) override {
parent_->OnResolverError(error);
}
private:
RefCountedPtr<ResolvingLoadBalancingPolicy> parent_;
};
//
// ResolvingLoadBalancingPolicy::ResolvingControlHelper
//
@ -196,12 +226,9 @@ ResolvingLoadBalancingPolicy::ResolvingLoadBalancingPolicy(
}
grpc_error* ResolvingLoadBalancingPolicy::Init(const grpc_channel_args& args) {
GRPC_CLOSURE_INIT(
&on_resolver_result_changed_,
&ResolvingLoadBalancingPolicy::OnResolverResultChangedLocked, this,
grpc_combiner_scheduler(combiner()));
resolver_ = ResolverRegistry::CreateResolver(
target_uri_.get(), &args, interested_parties(), combiner());
target_uri_.get(), &args, interested_parties(), combiner(),
UniquePtr<Resolver::ResultHandler>(New<ResolverResultHandler>(Ref())));
if (resolver_ == nullptr) {
return GRPC_ERROR_CREATE_FROM_STATIC_STRING("resolver creation failed");
}
@ -288,62 +315,34 @@ void ResolvingLoadBalancingPolicy::StartResolvingLocked() {
channel_control_helper()->UpdateState(
GRPC_CHANNEL_CONNECTING, GRPC_ERROR_NONE,
UniquePtr<SubchannelPicker>(New<QueuePicker>(Ref())));
Ref().release();
resolver_->NextLocked(&resolver_result_, &on_resolver_result_changed_);
resolver_->StartLocked();
}
// Invoked from the resolver NextLocked() callback when the resolver
// is shutting down.
void ResolvingLoadBalancingPolicy::OnResolverShutdownLocked(grpc_error* error) {
if (tracer_->enabled()) {
gpr_log(GPR_INFO, "resolving_lb=%p: shutting down", this);
void ResolvingLoadBalancingPolicy::OnResolverError(grpc_error* error) {
if (resolver_ == nullptr) {
GRPC_ERROR_UNREF(error);
return;
}
{
MutexLock lock(&lb_policy_mu_);
if (lb_policy_ != nullptr) {
if (tracer_->enabled()) {
gpr_log(GPR_INFO, "resolving_lb=%p: shutting down lb_policy=%p", this,
lb_policy_.get());
}
grpc_pollset_set_del_pollset_set(lb_policy_->interested_parties(),
interested_parties());
lb_policy_.reset();
}
if (pending_lb_policy_ != nullptr) {
if (tracer_->enabled()) {
gpr_log(GPR_INFO, "resolving_lb=%p: shutting down pending lb_policy=%p",
this, pending_lb_policy_.get());
}
grpc_pollset_set_del_pollset_set(pending_lb_policy_->interested_parties(),
interested_parties());
pending_lb_policy_.reset();
}
if (tracer_->enabled()) {
gpr_log(GPR_INFO, "resolving_lb=%p: resolver transient failure: %s", this,
grpc_error_string(error));
}
if (resolver_ != nullptr) {
// This should never happen; it can only be triggered by a resolver
// implementation spotaneously deciding to report shutdown without
// being orphaned. This code is included just to be defensive.
if (tracer_->enabled()) {
gpr_log(GPR_INFO,
"resolving_lb=%p: spontaneous shutdown from resolver %p", this,
resolver_.get());
}
resolver_.reset();
grpc_error* error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
"Resolver spontaneous shutdown", &error, 1);
// If we already have an LB policy from a previous resolution
// result, then we continue to let it set the connectivity state.
// Otherwise, we go into TRANSIENT_FAILURE.
if (lb_policy_ == nullptr) {
grpc_error* state_error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
"Resolver transient failure", &error, 1);
channel_control_helper()->UpdateState(
GRPC_CHANNEL_SHUTDOWN, GRPC_ERROR_REF(error),
UniquePtr<SubchannelPicker>(New<TransientFailurePicker>(error)));
GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_REF(state_error),
UniquePtr<SubchannelPicker>(New<TransientFailurePicker>(state_error)));
}
grpc_channel_args_destroy(resolver_result_);
resolver_result_ = nullptr;
GRPC_ERROR_UNREF(error);
Unref();
}
void ResolvingLoadBalancingPolicy::CreateOrUpdateLbPolicyLocked(
const char* lb_policy_name, RefCountedPtr<Config> lb_policy_config,
TraceStringVector* trace_strings) {
const grpc_channel_args& args, TraceStringVector* trace_strings) {
// If the child policy name changes, we need to create a new child
// policy. When this happens, we leave child_policy_ as-is and store
// the new child policy in pending_child_policy_. Once the new child
@ -411,7 +410,7 @@ void ResolvingLoadBalancingPolicy::CreateOrUpdateLbPolicyLocked(
gpr_log(GPR_INFO, "resolving_lb=%p: Creating new %schild policy %s", this,
lb_policy_ == nullptr ? "" : "pending ", lb_policy_name);
}
auto new_policy = CreateLbPolicyLocked(lb_policy_name, trace_strings);
auto new_policy = CreateLbPolicyLocked(lb_policy_name, args, trace_strings);
auto& lb_policy = lb_policy_ == nullptr ? lb_policy_ : pending_lb_policy_;
{
MutexLock lock(&lb_policy_mu_);
@ -432,21 +431,21 @@ void ResolvingLoadBalancingPolicy::CreateOrUpdateLbPolicyLocked(
policy_to_update == pending_lb_policy_.get() ? "pending " : "",
policy_to_update);
}
policy_to_update->UpdateLocked(*resolver_result_,
std::move(lb_policy_config));
policy_to_update->UpdateLocked(args, std::move(lb_policy_config));
}
// Creates a new LB policy.
// Updates trace_strings to indicate what was done.
OrphanablePtr<LoadBalancingPolicy>
ResolvingLoadBalancingPolicy::CreateLbPolicyLocked(
const char* lb_policy_name, TraceStringVector* trace_strings) {
const char* lb_policy_name, const grpc_channel_args& args,
TraceStringVector* trace_strings) {
ResolvingControlHelper* helper = New<ResolvingControlHelper>(Ref());
LoadBalancingPolicy::Args lb_policy_args;
lb_policy_args.combiner = combiner();
lb_policy_args.channel_control_helper =
UniquePtr<ChannelControlHelper>(helper);
lb_policy_args.args = resolver_result_;
lb_policy_args.args = &args;
OrphanablePtr<LoadBalancingPolicy> lb_policy =
LoadBalancingPolicyRegistry::CreateLoadBalancingPolicy(
lb_policy_name, std::move(lb_policy_args));
@ -480,9 +479,10 @@ ResolvingLoadBalancingPolicy::CreateLbPolicyLocked(
}
void ResolvingLoadBalancingPolicy::MaybeAddTraceMessagesForAddressChangesLocked(
const grpc_channel_args& resolver_result,
TraceStringVector* trace_strings) {
const ServerAddressList* addresses =
FindServerAddressListChannelArg(resolver_result_);
FindServerAddressListChannelArg(&resolver_result);
const bool resolution_contains_addresses =
addresses != nullptr && addresses->size() > 0;
if (!resolution_contains_addresses &&
@ -516,27 +516,16 @@ void ResolvingLoadBalancingPolicy::ConcatenateAndAddChannelTraceLocked(
}
}
// Callback invoked when a resolver result is available.
void ResolvingLoadBalancingPolicy::OnResolverResultChangedLocked(
void* arg, grpc_error* error) {
auto* self = static_cast<ResolvingLoadBalancingPolicy*>(arg);
if (self->tracer_->enabled()) {
const char* disposition =
self->resolver_result_ != nullptr
? ""
: (error == GRPC_ERROR_NONE ? " (transient error)"
: " (resolver shutdown)");
gpr_log(GPR_INFO,
"resolving_lb=%p: got resolver result: resolver_result=%p "
"error=%s%s",
self, self->resolver_result_, grpc_error_string(error),
disposition);
}
// Handle shutdown.
if (error != GRPC_ERROR_NONE || self->resolver_ == nullptr) {
self->OnResolverShutdownLocked(GRPC_ERROR_REF(error));
const grpc_channel_args* result) {
// Handle race conditions.
if (resolver_ == nullptr) {
grpc_channel_args_destroy(result);
return;
}
if (tracer_->enabled()) {
gpr_log(GPR_INFO, "resolving_lb=%p: got resolver result %p", this, result);
}
// We only want to trace the address resolution in the follow cases:
// (a) Address resolution resulted in service config change.
// (b) Address resolution that causes number of backends to go from
@ -547,63 +536,34 @@ void ResolvingLoadBalancingPolicy::OnResolverResultChangedLocked(
//
// we track a list of strings to eventually be concatenated and traced.
TraceStringVector trace_strings;
// resolver_result_ will be null in the case of a transient
// resolution error. In that case, we don't have any new result to
// process, which means that we keep using the previous result (if any).
if (self->resolver_result_ == nullptr) {
if (self->tracer_->enabled()) {
gpr_log(GPR_INFO, "resolving_lb=%p: resolver transient failure", self);
}
// If we already have an LB policy from a previous resolution
// result, then we continue to let it set the connectivity state.
// Otherwise, we go into TRANSIENT_FAILURE.
if (self->lb_policy_ == nullptr) {
// TODO(roth): When we change the resolver API to be able to
// return transient errors in a cleaner way, we should make it the
// resolver's responsibility to attach a status to the error,
// rather than doing it centrally here.
grpc_error* state_error = grpc_error_set_int(
GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
"Resolver transient failure", &error, 1),
GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
self->channel_control_helper()->UpdateState(
GRPC_CHANNEL_TRANSIENT_FAILURE, GRPC_ERROR_REF(state_error),
UniquePtr<SubchannelPicker>(
New<TransientFailurePicker>(state_error)));
}
// Parse the resolver result.
const char* lb_policy_name = nullptr;
RefCountedPtr<Config> lb_policy_config;
bool service_config_changed = false;
if (process_resolver_result_ != nullptr) {
service_config_changed =
process_resolver_result_(process_resolver_result_user_data_, *result,
&lb_policy_name, &lb_policy_config);
} else {
// Parse the resolver result.
const char* lb_policy_name = nullptr;
RefCountedPtr<Config> lb_policy_config;
bool service_config_changed = false;
if (self->process_resolver_result_ != nullptr) {
service_config_changed = self->process_resolver_result_(
self->process_resolver_result_user_data_, *self->resolver_result_,
&lb_policy_name, &lb_policy_config);
} else {
lb_policy_name = self->child_policy_name_.get();
lb_policy_config = self->child_lb_config_;
}
GPR_ASSERT(lb_policy_name != nullptr);
self->CreateOrUpdateLbPolicyLocked(
lb_policy_name, std::move(lb_policy_config), &trace_strings);
// Add channel trace event.
if (self->channelz_node() != nullptr) {
if (service_config_changed) {
// TODO(ncteisen): might be worth somehow including a snippet of the
// config in the trace, at the risk of bloating the trace logs.
trace_strings.push_back(gpr_strdup("Service config changed"));
}
self->MaybeAddTraceMessagesForAddressChangesLocked(&trace_strings);
self->ConcatenateAndAddChannelTraceLocked(&trace_strings);
lb_policy_name = child_policy_name_.get();
lb_policy_config = child_lb_config_;
}
GPR_ASSERT(lb_policy_name != nullptr);
// Create or update LB policy, as needed.
CreateOrUpdateLbPolicyLocked(lb_policy_name, std::move(lb_policy_config),
*result, &trace_strings);
// Add channel trace event.
if (channelz_node() != nullptr) {
if (service_config_changed) {
// TODO(ncteisen): might be worth somehow including a snippet of the
// config in the trace, at the risk of bloating the trace logs.
trace_strings.push_back(gpr_strdup("Service config changed"));
}
// Clean up.
grpc_channel_args_destroy(self->resolver_result_);
self->resolver_result_ = nullptr;
MaybeAddTraceMessagesForAddressChangesLocked(*result, &trace_strings);
ConcatenateAndAddChannelTraceLocked(&trace_strings);
}
// Renew resolver callback.
self->resolver_->NextLocked(&self->resolver_result_,
&self->on_resolver_result_changed_);
// Clean up.
grpc_channel_args_destroy(result);
}
} // namespace grpc_core

@ -93,6 +93,7 @@ class ResolvingLoadBalancingPolicy : public LoadBalancingPolicy {
private:
using TraceStringVector = InlinedVector<char*, 3>;
class ResolverResultHandler;
class ResolvingControlHelper;
~ResolvingLoadBalancingPolicy();
@ -101,17 +102,20 @@ class ResolvingLoadBalancingPolicy : public LoadBalancingPolicy {
void ShutdownLocked() override;
void StartResolvingLocked();
void OnResolverShutdownLocked(grpc_error* error);
void OnResolverError(grpc_error* error);
void CreateOrUpdateLbPolicyLocked(const char* lb_policy_name,
RefCountedPtr<Config>,
RefCountedPtr<Config> lb_policy_config,
const grpc_channel_args& args,
TraceStringVector* trace_strings);
OrphanablePtr<LoadBalancingPolicy> CreateLbPolicyLocked(
const char* lb_policy_name, TraceStringVector* trace_strings);
const char* lb_policy_name, const grpc_channel_args& args,
TraceStringVector* trace_strings);
void MaybeAddTraceMessagesForAddressChangesLocked(
const grpc_channel_args& resolver_result,
TraceStringVector* trace_strings);
void ConcatenateAndAddChannelTraceLocked(
TraceStringVector* trace_strings) const;
static void OnResolverResultChangedLocked(void* arg, grpc_error* error);
void OnResolverResultChangedLocked(const grpc_channel_args* result);
// Passed in from caller at construction time.
TraceFlag* tracer_;
@ -124,9 +128,7 @@ class ResolvingLoadBalancingPolicy : public LoadBalancingPolicy {
// Resolver and associated state.
OrphanablePtr<Resolver> resolver_;
bool started_resolving_ = false;
grpc_channel_args* resolver_result_ = nullptr;
bool previous_resolution_contained_addresses_ = false;
grpc_closure on_resolver_result_changed_;
// Child LB policy.
OrphanablePtr<LoadBalancingPolicy> lb_policy_;

@ -56,6 +56,9 @@ grpc_channel_args* grpc_channel_args_union(const grpc_channel_args* a,
/** Destroy arguments created by \a grpc_channel_args_copy */
void grpc_channel_args_destroy(grpc_channel_args* a);
inline void grpc_channel_args_destroy(const grpc_channel_args* a) {
grpc_channel_args_destroy(const_cast<grpc_channel_args*>(a));
}
/** Returns the compression algorithm set in \a a. */
grpc_compression_algorithm grpc_channel_args_get_compression_algorithm(

@ -170,6 +170,22 @@
#define GRPC_POSIX_SOCKET 1
#define GRPC_POSIX_SOCKETUTILS 1
#define GRPC_POSIX_WAKEUP_FD 1
#elif defined(GPR_FUCHSIA)
#define GRPC_HAVE_IFADDRS 1
#define GRPC_HAVE_IPV6_RECVPKTINFO 1
#define GRPC_HAVE_IP_PKTINFO 1
// Zircon does not support the MSG_NOSIGNAL flag since it doesn't support
// signals.
#undef GRPC_HAVE_MSG_NOSIGNAL
#define GRPC_HAVE_UNIX_SOCKET 1
#define GRPC_POSIX_WAKEUP_FD 1
// TODO(rudominer) Check that this does something we want.
#define GRPC_POSIX_NO_SPECIAL_WAKEUP_FD 1
#define GRPC_POSIX_SOCKET 1
#define GRPC_POSIX_SOCKETADDR 1
// TODO(rudominer) Check this does something we want.
#define GRPC_POSIX_SOCKETUTILS 1
#define GRPC_TIMER_USE_GENERIC 1
#elif !defined(GPR_NO_AUTODETECT_PLATFORM)
#error "Platform not recognized"
#endif

@ -28,7 +28,17 @@ experimental::ClientInterceptorFactoryInterface*
namespace experimental {
void RegisterGlobalClientInterceptorFactory(
ClientInterceptorFactoryInterface* factory) {
if (internal::g_global_client_interceptor_factory != nullptr) {
GPR_ASSERT(false &&
"It is illegal to call RegisterGlobalClientInterceptorFactory "
"multiple times.");
}
internal::g_global_client_interceptor_factory = factory;
}
// For testing purposes only.
void TestOnlyResetGlobalClientInterceptorFactory() {
internal::g_global_client_interceptor_factory = nullptr;
}
} // namespace experimental
} // namespace grpc

@ -0,0 +1,40 @@
#region Copyright notice and license
// Copyright 2019 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#endregion
using System;
namespace Grpc.Core.Internal
{
/// <summary>
/// Use this attribute to mark methods that will be called back from P/Invoke calls.
/// iOS (and probably other AOT platforms) needs to have delegates registered.
/// Instead of depending on Xamarin.iOS for this, we can just create our own,
/// the iOS runtime just checks for the type name.
/// See: https://docs.microsoft.com/en-gb/xamarin/ios/internals/limitations#reverse-callbacks
/// </summary>
[AttributeUsage(AttributeTargets.Method)]
internal sealed class MonoPInvokeCallbackAttribute : Attribute
{
public MonoPInvokeCallbackAttribute(Type type)
{
Type = type;
}
public Type Type { get; private set; }
}
}

@ -0,0 +1,91 @@
#region Copyright notice and license
// Copyright 2019 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#endregion
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using System.Collections.Generic;
using Grpc.Core.Logging;
using Grpc.Core.Utils;
namespace Grpc.Core.Internal
{
internal delegate int UniversalNativeCallback(IntPtr arg0, IntPtr arg1, IntPtr arg2, IntPtr arg3, IntPtr arg4, IntPtr arg5);
internal delegate int NativeCallbackDispatcherCallback(IntPtr tag, IntPtr arg0, IntPtr arg1, IntPtr arg2, IntPtr arg3, IntPtr arg4, IntPtr arg5);
internal class NativeCallbackDispatcher
{
static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<NativeCallbackDispatcher>();
static NativeCallbackDispatcherCallback dispatcherCallback;
public static void Init(NativeMethods native)
{
GrpcPreconditions.CheckState(dispatcherCallback == null);
dispatcherCallback = new NativeCallbackDispatcherCallback(HandleDispatcherCallback);
native.grpcsharp_native_callback_dispatcher_init(dispatcherCallback);
}
public static NativeCallbackRegistration RegisterCallback(UniversalNativeCallback callback)
{
var gcHandle = GCHandle.Alloc(callback);
return new NativeCallbackRegistration(gcHandle);
}
[MonoPInvokeCallback(typeof(NativeCallbackDispatcherCallback))]
private static int HandleDispatcherCallback(IntPtr tag, IntPtr arg0, IntPtr arg1, IntPtr arg2, IntPtr arg3, IntPtr arg4, IntPtr arg5)
{
try
{
var gcHandle = GCHandle.FromIntPtr(tag);
var callback = (UniversalNativeCallback) gcHandle.Target;
return callback(arg0, arg1, arg2, arg3, arg4, arg5);
}
catch (Exception e)
{
// eat the exception, we must not throw when inside callback from native code.
Logger.Error(e, "Caught exception inside callback from native callback.");
return 0;
}
}
}
internal class NativeCallbackRegistration : IDisposable
{
readonly GCHandle handle;
public NativeCallbackRegistration(GCHandle handle)
{
this.handle = handle;
}
public IntPtr Tag => GCHandle.ToIntPtr(handle);
public void Dispose()
{
if (handle.IsAllocated)
{
handle.Free();
}
}
}
}

@ -43,6 +43,9 @@ namespace Grpc.Core.Internal
// to make sure we don't lose any logs.
NativeLogRedirector.Redirect(this.nativeMethods);
// Initialize
NativeCallbackDispatcher.Init(this.nativeMethods);
DefaultSslRootsOverride.Override(this.nativeMethods);
Logger.Debug("gRPC native library loaded successfully.");

@ -87,22 +87,4 @@ namespace Grpc.Core.Internal
}
}
}
/// <summary>
/// Use this attribute to mark methods that will be called back from P/Invoke calls.
/// iOS (and probably other AOT platforms) needs to have delegates registered.
/// Instead of depending on Xamarin.iOS for this, we can just create our own,
/// the iOS runtime just checks for the type name.
/// See: https://docs.microsoft.com/en-gb/xamarin/ios/internals/limitations#reverse-callbacks
/// </summary>
[AttributeUsage(AttributeTargets.Method)]
internal sealed class MonoPInvokeCallbackAttribute : Attribute
{
public MonoPInvokeCallbackAttribute(Type type)
{
Type = type;
}
public Type Type { get; private set; }
}
}

@ -23,8 +23,6 @@ using Grpc.Core.Utils;
namespace Grpc.Core.Internal
{
internal delegate void NativeMetadataInterceptor(IntPtr statePtr, IntPtr serviceUrlPtr, IntPtr methodNamePtr, IntPtr callbackPtr, IntPtr userDataPtr, bool isDestroy);
internal class NativeMetadataCredentialsPlugin
{
const string GetMetadataExceptionStatusMsg = "Exception occurred in metadata credentials plugin.";
@ -33,18 +31,14 @@ namespace Grpc.Core.Internal
static readonly NativeMethods Native = NativeMethods.Get();
AsyncAuthInterceptor interceptor;
GCHandle gcHandle;
NativeMetadataInterceptor nativeInterceptor;
CallCredentialsSafeHandle credentials;
NativeCallbackRegistration callbackRegistration;
public NativeMetadataCredentialsPlugin(AsyncAuthInterceptor interceptor)
{
this.interceptor = GrpcPreconditions.CheckNotNull(interceptor, "interceptor");
this.nativeInterceptor = NativeMetadataInterceptorHandler;
// Make sure the callback doesn't get garbage collected until it is destroyed.
this.gcHandle = GCHandle.Alloc(this.nativeInterceptor, GCHandleType.Normal);
this.credentials = Native.grpcsharp_metadata_credentials_create_from_plugin(nativeInterceptor);
this.callbackRegistration = NativeCallbackDispatcher.RegisterCallback(HandleUniversalCallback);
this.credentials = Native.grpcsharp_metadata_credentials_create_from_plugin(this.callbackRegistration.Tag);
}
public CallCredentialsSafeHandle Credentials
@ -52,11 +46,17 @@ namespace Grpc.Core.Internal
get { return credentials; }
}
private void NativeMetadataInterceptorHandler(IntPtr statePtr, IntPtr serviceUrlPtr, IntPtr methodNamePtr, IntPtr callbackPtr, IntPtr userDataPtr, bool isDestroy)
private int HandleUniversalCallback(IntPtr arg0, IntPtr arg1, IntPtr arg2, IntPtr arg3, IntPtr arg4, IntPtr arg5)
{
NativeMetadataInterceptorHandler(arg0, arg1, arg2, arg3, arg4 != IntPtr.Zero);
return 0;
}
private void NativeMetadataInterceptorHandler(IntPtr serviceUrlPtr, IntPtr methodNamePtr, IntPtr callbackPtr, IntPtr userDataPtr, bool isDestroy)
{
if (isDestroy)
{
gcHandle.Free();
this.callbackRegistration.Dispose();
return;
}

@ -103,6 +103,7 @@ namespace Grpc.Core.Internal
public readonly Delegates.grpcsharp_metadata_array_get_value_delegate grpcsharp_metadata_array_get_value;
public readonly Delegates.grpcsharp_metadata_array_destroy_full_delegate grpcsharp_metadata_array_destroy_full;
public readonly Delegates.grpcsharp_redirect_log_delegate grpcsharp_redirect_log;
public readonly Delegates.grpcsharp_native_callback_dispatcher_init_delegate grpcsharp_native_callback_dispatcher_init;
public readonly Delegates.grpcsharp_metadata_credentials_create_from_plugin_delegate grpcsharp_metadata_credentials_create_from_plugin;
public readonly Delegates.grpcsharp_metadata_credentials_notify_from_plugin_delegate grpcsharp_metadata_credentials_notify_from_plugin;
public readonly Delegates.grpcsharp_ssl_server_credentials_create_delegate grpcsharp_ssl_server_credentials_create;
@ -203,6 +204,7 @@ namespace Grpc.Core.Internal
this.grpcsharp_metadata_array_get_value = GetMethodDelegate<Delegates.grpcsharp_metadata_array_get_value_delegate>(library);
this.grpcsharp_metadata_array_destroy_full = GetMethodDelegate<Delegates.grpcsharp_metadata_array_destroy_full_delegate>(library);
this.grpcsharp_redirect_log = GetMethodDelegate<Delegates.grpcsharp_redirect_log_delegate>(library);
this.grpcsharp_native_callback_dispatcher_init = GetMethodDelegate<Delegates.grpcsharp_native_callback_dispatcher_init_delegate>(library);
this.grpcsharp_metadata_credentials_create_from_plugin = GetMethodDelegate<Delegates.grpcsharp_metadata_credentials_create_from_plugin_delegate>(library);
this.grpcsharp_metadata_credentials_notify_from_plugin = GetMethodDelegate<Delegates.grpcsharp_metadata_credentials_notify_from_plugin_delegate>(library);
this.grpcsharp_ssl_server_credentials_create = GetMethodDelegate<Delegates.grpcsharp_ssl_server_credentials_create_delegate>(library);
@ -302,6 +304,7 @@ namespace Grpc.Core.Internal
this.grpcsharp_metadata_array_get_value = DllImportsFromStaticLib.grpcsharp_metadata_array_get_value;
this.grpcsharp_metadata_array_destroy_full = DllImportsFromStaticLib.grpcsharp_metadata_array_destroy_full;
this.grpcsharp_redirect_log = DllImportsFromStaticLib.grpcsharp_redirect_log;
this.grpcsharp_native_callback_dispatcher_init = DllImportsFromStaticLib.grpcsharp_native_callback_dispatcher_init;
this.grpcsharp_metadata_credentials_create_from_plugin = DllImportsFromStaticLib.grpcsharp_metadata_credentials_create_from_plugin;
this.grpcsharp_metadata_credentials_notify_from_plugin = DllImportsFromStaticLib.grpcsharp_metadata_credentials_notify_from_plugin;
this.grpcsharp_ssl_server_credentials_create = DllImportsFromStaticLib.grpcsharp_ssl_server_credentials_create;
@ -401,6 +404,7 @@ namespace Grpc.Core.Internal
this.grpcsharp_metadata_array_get_value = DllImportsFromSharedLib.grpcsharp_metadata_array_get_value;
this.grpcsharp_metadata_array_destroy_full = DllImportsFromSharedLib.grpcsharp_metadata_array_destroy_full;
this.grpcsharp_redirect_log = DllImportsFromSharedLib.grpcsharp_redirect_log;
this.grpcsharp_native_callback_dispatcher_init = DllImportsFromSharedLib.grpcsharp_native_callback_dispatcher_init;
this.grpcsharp_metadata_credentials_create_from_plugin = DllImportsFromSharedLib.grpcsharp_metadata_credentials_create_from_plugin;
this.grpcsharp_metadata_credentials_notify_from_plugin = DllImportsFromSharedLib.grpcsharp_metadata_credentials_notify_from_plugin;
this.grpcsharp_ssl_server_credentials_create = DllImportsFromSharedLib.grpcsharp_ssl_server_credentials_create;
@ -503,7 +507,8 @@ namespace Grpc.Core.Internal
public delegate IntPtr grpcsharp_metadata_array_get_value_delegate(IntPtr metadataArray, UIntPtr index, out UIntPtr valueLength);
public delegate void grpcsharp_metadata_array_destroy_full_delegate(IntPtr array);
public delegate void grpcsharp_redirect_log_delegate(GprLogDelegate callback);
public delegate CallCredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin_delegate(NativeMetadataInterceptor interceptor);
public delegate void grpcsharp_native_callback_dispatcher_init_delegate(NativeCallbackDispatcherCallback dispatcher);
public delegate CallCredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin_delegate(IntPtr nativeCallbackTag);
public delegate void grpcsharp_metadata_credentials_notify_from_plugin_delegate(IntPtr callbackPtr, IntPtr userData, MetadataArraySafeHandle metadataArray, StatusCode statusCode, string errorDetails);
public delegate ServerCredentialsSafeHandle grpcsharp_ssl_server_credentials_create_delegate(string pemRootCerts, string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray, UIntPtr numKeyCertPairs, SslClientCertificateRequestType clientCertificateRequest);
public delegate void grpcsharp_server_credentials_release_delegate(IntPtr credentials);
@ -746,7 +751,10 @@ namespace Grpc.Core.Internal
public static extern void grpcsharp_redirect_log(GprLogDelegate callback);
[DllImport(ImportName)]
public static extern CallCredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin(NativeMetadataInterceptor interceptor);
public static extern void grpcsharp_native_callback_dispatcher_init(NativeCallbackDispatcherCallback dispatcher);
[DllImport(ImportName)]
public static extern CallCredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin(IntPtr nativeCallbackTag);
[DllImport(ImportName)]
public static extern void grpcsharp_metadata_credentials_notify_from_plugin(IntPtr callbackPtr, IntPtr userData, MetadataArraySafeHandle metadataArray, StatusCode statusCode, string errorDetails);
@ -1039,7 +1047,10 @@ namespace Grpc.Core.Internal
public static extern void grpcsharp_redirect_log(GprLogDelegate callback);
[DllImport(ImportName)]
public static extern CallCredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin(NativeMetadataInterceptor interceptor);
public static extern void grpcsharp_native_callback_dispatcher_init(NativeCallbackDispatcherCallback dispatcher);
[DllImport(ImportName)]
public static extern CallCredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin(IntPtr nativeCallbackTag);
[DllImport(ImportName)]
public static extern void grpcsharp_metadata_credentials_notify_from_plugin(IntPtr callbackPtr, IntPtr userData, MetadataArraySafeHandle metadataArray, StatusCode statusCode, string errorDetails);

@ -1010,6 +1010,21 @@ grpcsharp_composite_call_credentials_create(grpc_call_credentials* creds1,
return grpc_composite_call_credentials_create(creds1, creds2, NULL);
}
/* Native callback dispatcher */
typedef int(GPR_CALLTYPE* grpcsharp_native_callback_dispatcher_func)(
void* tag, void* arg0, void* arg1, void* arg2, void* arg3, void* arg4,
void* arg5);
static grpcsharp_native_callback_dispatcher_func native_callback_dispatcher =
NULL;
GPR_EXPORT void GPR_CALLTYPE grpcsharp_native_callback_dispatcher_init(
grpcsharp_native_callback_dispatcher_func func) {
GPR_ASSERT(func);
native_callback_dispatcher = func;
}
/* Metadata credentials plugin */
GPR_EXPORT void GPR_CALLTYPE grpcsharp_metadata_credentials_notify_from_plugin(
@ -1023,37 +1038,28 @@ GPR_EXPORT void GPR_CALLTYPE grpcsharp_metadata_credentials_notify_from_plugin(
}
}
typedef void(GPR_CALLTYPE* grpcsharp_metadata_interceptor_func)(
void* state, const char* service_url, const char* method_name,
grpc_credentials_plugin_metadata_cb cb, void* user_data,
int32_t is_destroy);
static int grpcsharp_get_metadata_handler(
void* state, grpc_auth_metadata_context context,
grpc_credentials_plugin_metadata_cb cb, void* user_data,
grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX],
size_t* num_creds_md, grpc_status_code* status,
const char** error_details) {
grpcsharp_metadata_interceptor_func interceptor =
(grpcsharp_metadata_interceptor_func)(intptr_t)state;
interceptor(state, context.service_url, context.method_name, cb, user_data,
0);
native_callback_dispatcher(state, (void*)context.service_url,
(void*)context.method_name, cb, user_data,
(void*)0, NULL);
return 0; /* Asynchronous return. */
}
static void grpcsharp_metadata_credentials_destroy_handler(void* state) {
grpcsharp_metadata_interceptor_func interceptor =
(grpcsharp_metadata_interceptor_func)(intptr_t)state;
interceptor(state, NULL, NULL, NULL, NULL, 1);
native_callback_dispatcher(state, NULL, NULL, NULL, NULL, (void*)1, NULL);
}
GPR_EXPORT grpc_call_credentials* GPR_CALLTYPE
grpcsharp_metadata_credentials_create_from_plugin(
grpcsharp_metadata_interceptor_func metadata_interceptor) {
grpcsharp_metadata_credentials_create_from_plugin(void* callback_tag) {
grpc_metadata_credentials_plugin plugin;
plugin.get_metadata = grpcsharp_get_metadata_handler;
plugin.destroy = grpcsharp_metadata_credentials_destroy_handler;
plugin.state = (void*)(intptr_t)metadata_interceptor;
plugin.state = callback_tag;
plugin.type = "";
return grpc_metadata_credentials_create_from_plugin(plugin, NULL);
}

@ -298,6 +298,10 @@ void grpcsharp_redirect_log() {
fprintf(stderr, "Should never reach here");
abort();
}
void grpcsharp_native_callback_dispatcher_init() {
fprintf(stderr, "Should never reach here");
abort();
}
void grpcsharp_metadata_credentials_create_from_plugin() {
fprintf(stderr, "Should never reach here");
abort();

@ -0,0 +1,220 @@
%YAML 1.2
--- |
# GRPC Fuchsia GN build file
# This file has been automatically generated from a template file.
# Please look at the templates directory instead.
# This file can be regenerated from the template by running
# tools/buildgen/generate_projects.sh
# Copyright 2019 gRPC authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
config("grpc_config") {
include_dirs = [
".",
"include/",
]
defines = [
"GRPC_USE_PROTO_LITE",
"GPR_SUPPORT_CHANNELS_FROM_FD",
"PB_FIELD_16BIT",
]
}
<%!
def get_deps(target_dict):
deps = []
if target_dict.get("secure", False):
deps = ["//third_party/boringssl"]
if target_dict.get("build", None) == "protoc":
deps.append("//third_party/protobuf:protoc_lib")
name = target_dict.get("name", None)
if name in ("grpc++", "grpc++_codegen_lib"):
deps.append("//third_party/protobuf:protobuf_lite")
elif name in ("grpc", "grpc_unsecure"):
deps.append("//third_party/zlib")
for d in target_dict.get("deps", []):
if d.startswith(("//", ":")):
deps.append(d)
else:
deps.append(":%s" % d)
if needs_ares(target_dict.src):
deps.append("//third_party/cares")
deps.append(":address_sorting")
if needs_nanopb(target_dict.src) and target_dict.name != "nanopb":
deps.append(":nanopb")
if needs_health_proto(target_dict.src) and target_dict.name != "health_proto":
deps.append(":health_proto")
return deps
%><%!
def needs_ares(srcs):
return any("/c_ares/" in f for f in srcs) if srcs else False
%><%!
def needs_nanopb(srcs):
return any(f.startswith("third_party/nanopb")
or f.endswith(".pb.h")
or f.endswith(".pb.c")
or f.endswith(".pb.cc")
or f.endswith("load_balancer_api.h")
or f.endswith("load_balancer_api.c")
for f in srcs)
%><%!
def needs_address_sorting(sources):
return needs_ares(sources) or any("address_sorting" in s for s in sources)
%><%!
def needs_health_proto(srcs):
return any("health.pb" in f for f in srcs)
%><%!
def get_include_dirs(sources):
dirs = []
if needs_ares(sources):
dirs = ["third_party/cares"]
if needs_address_sorting(sources):
dirs.append("third_party/address_sorting/include")
if needs_nanopb(sources):
dirs.append("third_party/nanopb")
return dirs
%><%!
def strip_sources(sources, name):
return [f for f in sources
if "ruby_generator" not in f
and ("third_party/nanopb" not in f or name == "nanopb")
and ("health.pb" not in f or name == "health_proto")]
%><%!
def get_sources(target):
return ((target.public_headers or []) +
(target.headers or []) +
(target.src or []))
%><%!
def get_extra_configs(target_dict):
if target_dict.get("name", "") == "grpc_cpp_plugin":
return ["//third_party/protobuf:protobuf_config"]
return []
%><%!
def wanted_lib(lib):
wanted_libs = ("gpr", "grpc", "grpc++", "grpc_plugin_support", "address_sorting")
return lib.build in ("all", "protoc") and lib.get("name", "") in wanted_libs
%><%!
def wanted_binary(tgt):
wanted_binaries = ("grpc_cpp_plugin",)
return tgt.build == "protoc" and tgt.get("name", "") in wanted_binaries
%><%!
def only_on_host_toolchain(tgt):
return tgt.get("name", "") in ("grpc_plugin_support", "grpc_cpp_plugin")
%>
% for lib in filegroups:
% if lib.name in ("nanopb", "health_proto"):
${cc_library(lib)}
%endif
%endfor
% for lib in libs:
% if wanted_lib(lib):
% if only_on_host_toolchain(lib):
# Only compile the plugin for the host architecture.
if (current_toolchain == host_toolchain) {
${cc_library(lib)}
}
% else:
${cc_library(lib)}
% endif
% endif
% endfor
% for tgt in targets:
% if wanted_binary(tgt):
% if only_on_host_toolchain(tgt):
# Only compile the plugin for the host architecture.
if (current_toolchain == host_toolchain) {
${cc_binary(tgt)}
}
% else:
${cc_binary(tgt)}
% endif
% endif
% endfor
<%def name="cc_library(lib)">
<%
sources = get_sources(lib)
include_dirs = get_include_dirs(sources)
sources = strip_sources(sources, lib.name)
sources.sort()
%>
source_set("${lib.name}") {
%if sources:
sources = [
% for src in sources:
"${src}",
% endfor
]
%endif
deps = [
% for dep in get_deps(lib):
"${dep}",
% endfor
]
<% extra_configs = get_extra_configs(lib) %>
% if extra_configs:
configs += [
% for config in extra_configs:
"${config}",
% endfor
]
% endif
public_configs = [
":grpc_config",
]
%if include_dirs:
include_dirs = [
%for d in include_dirs:
"${d}",
%endfor
]
%endif
}
</%def>
<%def name="cc_binary(tgt)">
executable("${tgt.name}") {
sources = [
% for src in tgt.src:
"${src}",
% endfor
]
deps = [
% for dep in get_deps(tgt):
"${dep}",
% endfor
]
<% extra_configs = get_extra_configs(tgt) %>
% if extra_configs:
configs += [
% for config in extra_configs:
"${config}",
% endfor
]
% endif
public_configs = [ ":grpc_config" ]
}
</%def>
## vim: set ft=mako:ts=2:et:sw=2

@ -69,7 +69,8 @@ native_method_signatures = [
'IntPtr grpcsharp_metadata_array_get_value(IntPtr metadataArray, UIntPtr index, out UIntPtr valueLength)',
'void grpcsharp_metadata_array_destroy_full(IntPtr array)',
'void grpcsharp_redirect_log(GprLogDelegate callback)',
'CallCredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin(NativeMetadataInterceptor interceptor)',
'void grpcsharp_native_callback_dispatcher_init(NativeCallbackDispatcherCallback dispatcher)',
'CallCredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin(IntPtr nativeCallbackTag)',
'void grpcsharp_metadata_credentials_notify_from_plugin(IntPtr callbackPtr, IntPtr userData, MetadataArraySafeHandle metadataArray, StatusCode statusCode, string errorDetails)',
'ServerCredentialsSafeHandle grpcsharp_ssl_server_credentials_create(string pemRootCerts, string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray, UIntPtr numKeyCertPairs, SslClientCertificateRequestType clientCertificateRequest)',
'void grpcsharp_server_credentials_release(IntPtr credentials)',

@ -90,7 +90,8 @@ static void my_cancel_ares_request_locked(grpc_ares_request* request) {
}
static grpc_core::OrphanablePtr<grpc_core::Resolver> create_resolver(
const char* name) {
const char* name,
grpc_core::UniquePtr<grpc_core::Resolver::ResultHandler> result_handler) {
grpc_core::ResolverFactory* factory =
grpc_core::ResolverRegistry::LookupResolverFactory("dns");
grpc_uri* uri = grpc_uri_parse(name, 0);
@ -98,15 +99,52 @@ static grpc_core::OrphanablePtr<grpc_core::Resolver> create_resolver(
grpc_core::ResolverArgs args;
args.uri = uri;
args.combiner = g_combiner;
args.result_handler = std::move(result_handler);
grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
factory->CreateResolver(args);
factory->CreateResolver(std::move(args));
grpc_uri_destroy(uri);
return resolver;
}
static void on_done(void* ev, grpc_error* error) {
gpr_event_set(static_cast<gpr_event*>(ev), (void*)1);
}
class ResultHandler : public grpc_core::Resolver::ResultHandler {
public:
struct ResolverOutput {
const grpc_channel_args* result = nullptr;
grpc_error* error = nullptr;
gpr_event ev;
ResolverOutput() { gpr_event_init(&ev); }
~ResolverOutput() {
grpc_channel_args_destroy(result);
GRPC_ERROR_UNREF(error);
}
};
void SetOutput(ResolverOutput* output) {
gpr_atm_rel_store(&output_, reinterpret_cast<gpr_atm>(output));
}
void ReturnResult(const grpc_channel_args* args) override {
ResolverOutput* output =
reinterpret_cast<ResolverOutput*>(gpr_atm_acq_load(&output_));
GPR_ASSERT(output != nullptr);
output->result = args;
output->error = GRPC_ERROR_NONE;
gpr_event_set(&output->ev, (void*)1);
}
void ReturnError(grpc_error* error) override {
ResolverOutput* output =
reinterpret_cast<ResolverOutput*>(gpr_atm_acq_load(&output_));
GPR_ASSERT(output != nullptr);
output->result = nullptr;
output->error = error;
gpr_event_set(&output->ev, (void*)1);
}
private:
gpr_atm output_ = 0; // ResolverOutput*
};
// interleave waiting for an event with a timer check
static bool wait_loop(int deadline_seconds, gpr_event* ev) {
@ -121,32 +159,6 @@ static bool wait_loop(int deadline_seconds, gpr_event* ev) {
return false;
}
typedef struct next_args {
grpc_core::Resolver* resolver;
grpc_channel_args** result;
grpc_closure* on_complete;
} next_args;
static void call_resolver_next_now_lock_taken(void* arg,
grpc_error* error_unused) {
next_args* a = static_cast<next_args*>(arg);
a->resolver->NextLocked(a->result, a->on_complete);
gpr_free(a);
}
static void call_resolver_next_after_locking(grpc_core::Resolver* resolver,
grpc_channel_args** result,
grpc_closure* on_complete,
grpc_combiner* combiner) {
next_args* a = static_cast<next_args*>(gpr_malloc(sizeof(*a)));
a->resolver = resolver;
a->result = result;
a->on_complete = on_complete;
GRPC_CLOSURE_SCHED(GRPC_CLOSURE_CREATE(call_resolver_next_now_lock_taken, a,
grpc_combiner_scheduler(combiner)),
GRPC_ERROR_NONE);
}
int main(int argc, char** argv) {
grpc::testing::TestEnvironment env(argc, argv);
@ -156,33 +168,28 @@ int main(int argc, char** argv) {
grpc_set_resolver_impl(&test_resolver);
grpc_dns_lookup_ares_locked = my_dns_lookup_ares_locked;
grpc_cancel_ares_request_locked = my_cancel_ares_request_locked;
grpc_channel_args* result = (grpc_channel_args*)1;
{
grpc_core::ExecCtx exec_ctx;
grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
create_resolver("dns:test");
gpr_event ev1;
gpr_event_init(&ev1);
call_resolver_next_after_locking(
resolver.get(), &result,
GRPC_CLOSURE_CREATE(on_done, &ev1, grpc_schedule_on_exec_ctx),
g_combiner);
ResultHandler* result_handler = grpc_core::New<ResultHandler>();
grpc_core::OrphanablePtr<grpc_core::Resolver> resolver = create_resolver(
"dns:test", grpc_core::UniquePtr<grpc_core::Resolver::ResultHandler>(
result_handler));
ResultHandler::ResolverOutput output1;
result_handler->SetOutput(&output1);
resolver->StartLocked();
grpc_core::ExecCtx::Get()->Flush();
GPR_ASSERT(wait_loop(5, &ev1));
GPR_ASSERT(result == nullptr);
gpr_event ev2;
gpr_event_init(&ev2);
call_resolver_next_after_locking(
resolver.get(), &result,
GRPC_CLOSURE_CREATE(on_done, &ev2, grpc_schedule_on_exec_ctx),
g_combiner);
GPR_ASSERT(wait_loop(5, &output1.ev));
GPR_ASSERT(output1.result == nullptr);
GPR_ASSERT(output1.error != GRPC_ERROR_NONE);
ResultHandler::ResolverOutput output2;
result_handler->SetOutput(&output2);
grpc_core::ExecCtx::Get()->Flush();
GPR_ASSERT(wait_loop(30, &ev2));
GPR_ASSERT(result != nullptr);
GPR_ASSERT(wait_loop(30, &output2.ev));
GPR_ASSERT(output2.result != nullptr);
GPR_ASSERT(output2.error == GRPC_ERROR_NONE);
grpc_channel_args_destroy(result);
GRPC_COMBINER_UNREF(g_combiner, "test");
}

@ -170,19 +170,52 @@ static void poll_pollset_until_request_done(iomgr_args* args) {
gpr_event_set(&args->ev, (void*)1);
}
struct OnResolutionCallbackArg;
class ResultHandler : public grpc_core::Resolver::ResultHandler {
public:
using ResultCallback = void (*)(const grpc_channel_args* result,
OnResolutionCallbackArg* state);
void SetCallback(ResultCallback result_cb, OnResolutionCallbackArg* state) {
GPR_ASSERT(result_cb_ == nullptr);
result_cb_ = result_cb;
GPR_ASSERT(state_ == nullptr);
state_ = state;
}
void ReturnResult(const grpc_channel_args* args) override {
GPR_ASSERT(result_cb_ != nullptr);
GPR_ASSERT(state_ != nullptr);
ResultCallback cb = result_cb_;
OnResolutionCallbackArg* state = state_;
result_cb_ = nullptr;
state_ = nullptr;
cb(args, state);
}
void ReturnError(grpc_error* error) override {
gpr_log(GPR_ERROR, "resolver returned error: %s", grpc_error_string(error));
GPR_ASSERT(false);
}
private:
ResultCallback result_cb_ = nullptr;
OnResolutionCallbackArg* state_ = nullptr;
};
struct OnResolutionCallbackArg {
const char* uri_str = nullptr;
grpc_core::OrphanablePtr<grpc_core::Resolver> resolver;
grpc_channel_args* result = nullptr;
ResultHandler* result_handler;
};
// Set to true by the last callback in the resolution chain.
static bool g_all_callbacks_invoked;
static void on_second_resolution(void* arg, grpc_error* error) {
OnResolutionCallbackArg* cb_arg = static_cast<OnResolutionCallbackArg*>(arg);
grpc_channel_args_destroy(cb_arg->result);
GPR_ASSERT(error == GRPC_ERROR_NONE);
static void on_second_resolution(const grpc_channel_args* result,
OnResolutionCallbackArg* cb_arg) {
grpc_channel_args_destroy(result);
gpr_log(GPR_INFO, "2nd: g_resolution_count: %d", g_resolution_count);
// The resolution callback was not invoked until new data was
// available, which was delayed until after the cooldown period.
@ -197,18 +230,14 @@ static void on_second_resolution(void* arg, grpc_error* error) {
g_all_callbacks_invoked = true;
}
static void on_first_resolution(void* arg, grpc_error* error) {
OnResolutionCallbackArg* cb_arg = static_cast<OnResolutionCallbackArg*>(arg);
grpc_channel_args_destroy(cb_arg->result);
GPR_ASSERT(error == GRPC_ERROR_NONE);
static void on_first_resolution(const grpc_channel_args* result,
OnResolutionCallbackArg* cb_arg) {
grpc_channel_args_destroy(result);
gpr_log(GPR_INFO, "1st: g_resolution_count: %d", g_resolution_count);
// There's one initial system-level resolution and one invocation of a
// notification callback (the current function).
GPR_ASSERT(g_resolution_count == 1);
cb_arg->resolver->NextLocked(
&cb_arg->result,
GRPC_CLOSURE_CREATE(on_second_resolution, arg,
grpc_combiner_scheduler(g_combiner)));
cb_arg->result_handler->SetCallback(on_second_resolution, cb_arg);
cb_arg->resolver->RequestReresolutionLocked();
gpr_mu_lock(g_iomgr_args.mu);
GRPC_LOG_IF_ERROR("pollset_kick",
@ -220,6 +249,8 @@ static void start_test_under_combiner(void* arg, grpc_error* error) {
OnResolutionCallbackArg* res_cb_arg =
static_cast<OnResolutionCallbackArg*>(arg);
res_cb_arg->result_handler = grpc_core::New<ResultHandler>();
grpc_core::ResolverFactory* factory =
grpc_core::ResolverRegistry::LookupResolverFactory("dns");
grpc_uri* uri = grpc_uri_parse(res_cb_arg->uri_str, 0);
@ -229,25 +260,22 @@ static void start_test_under_combiner(void* arg, grpc_error* error) {
grpc_core::ResolverArgs args;
args.uri = uri;
args.combiner = g_combiner;
args.result_handler =
grpc_core::UniquePtr<grpc_core::Resolver::ResultHandler>(
res_cb_arg->result_handler);
g_resolution_count = 0;
grpc_arg cooldown_arg;
cooldown_arg.key =
const_cast<char*>(GRPC_ARG_DNS_MIN_TIME_BETWEEN_RESOLUTIONS_MS);
cooldown_arg.type = GRPC_ARG_INTEGER;
cooldown_arg.value.integer = kMinResolutionPeriodMs;
auto* cooldown_channel_args =
grpc_channel_args_copy_and_add(nullptr, &cooldown_arg, 1);
args.args = cooldown_channel_args;
res_cb_arg->resolver = factory->CreateResolver(args);
grpc_channel_args_destroy(cooldown_channel_args);
grpc_arg cooldown_arg = grpc_channel_arg_integer_create(
const_cast<char*>(GRPC_ARG_DNS_MIN_TIME_BETWEEN_RESOLUTIONS_MS),
kMinResolutionPeriodMs);
grpc_channel_args cooldown_args = {1, &cooldown_arg};
args.args = &cooldown_args;
res_cb_arg->resolver = factory->CreateResolver(std::move(args));
GPR_ASSERT(res_cb_arg->resolver != nullptr);
// First resolution, would incur in system-level resolution.
res_cb_arg->resolver->NextLocked(
&res_cb_arg->result,
GRPC_CLOSURE_CREATE(on_first_resolution, res_cb_arg,
grpc_combiner_scheduler(g_combiner)));
grpc_uri_destroy(uri);
// First resolution, would incur in system-level resolution.
res_cb_arg->result_handler->SetCallback(on_first_resolution, res_cb_arg);
res_cb_arg->resolver->StartLocked();
}
static void test_cooldown() {

@ -39,8 +39,10 @@ static void test_succeeds(grpc_core::ResolverFactory* factory,
grpc_core::ResolverArgs args;
args.uri = uri;
args.combiner = g_combiner;
args.result_handler =
grpc_core::MakeUnique<grpc_core::Resolver::ResultHandler>();
grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
factory->CreateResolver(args);
factory->CreateResolver(std::move(args));
GPR_ASSERT(resolver != nullptr);
grpc_uri_destroy(uri);
}
@ -55,8 +57,10 @@ static void test_fails(grpc_core::ResolverFactory* factory,
grpc_core::ResolverArgs args;
args.uri = uri;
args.combiner = g_combiner;
args.result_handler =
grpc_core::MakeUnique<grpc_core::Resolver::ResultHandler>();
grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
factory->CreateResolver(args);
factory->CreateResolver(std::move(args));
GPR_ASSERT(resolver == nullptr);
grpc_uri_destroy(uri);
}

@ -33,9 +33,49 @@
#include "test/core/util/test_config.h"
class ResultHandler : public grpc_core::Resolver::ResultHandler {
public:
~ResultHandler() override { grpc_channel_args_destroy(expected_); }
void SetExpectedAndEvent(grpc_channel_args* expected, gpr_event* ev) {
GPR_ASSERT(expected_ == nullptr);
GPR_ASSERT(ev_ == nullptr);
expected_ = grpc_channel_args_copy(expected);
ev_ = ev;
}
void ReturnResult(const grpc_channel_args* args) override {
GPR_ASSERT(expected_ != nullptr);
GPR_ASSERT(ev_ != nullptr);
// We only check the addresses channel arg because that's the only one
// explicitly set by the test via
// FakeResolverResponseGenerator::SetResponse().
const grpc_core::ServerAddressList* actual_addresses =
grpc_core::FindServerAddressListChannelArg(args);
const grpc_core::ServerAddressList* expected_addresses =
grpc_core::FindServerAddressListChannelArg(expected_);
GPR_ASSERT(actual_addresses->size() == expected_addresses->size());
for (size_t i = 0; i < expected_addresses->size(); ++i) {
GPR_ASSERT((*actual_addresses)[i] == (*expected_addresses)[i]);
}
grpc_channel_args_destroy(args);
grpc_channel_args_destroy(expected_);
expected_ = nullptr;
gpr_event_set(ev_, (void*)1);
ev_ = nullptr;
}
void ReturnError(grpc_error* error) override {}
private:
grpc_channel_args* expected_ = nullptr;
gpr_event* ev_ = nullptr;
};
static grpc_core::OrphanablePtr<grpc_core::Resolver> build_fake_resolver(
grpc_combiner* combiner,
grpc_core::FakeResolverResponseGenerator* response_generator) {
grpc_core::FakeResolverResponseGenerator* response_generator,
grpc_core::UniquePtr<grpc_core::Resolver::ResultHandler> result_handler) {
grpc_core::ResolverFactory* factory =
grpc_core::ResolverRegistry::LookupResolverFactory("fake");
grpc_arg generator_arg =
@ -45,37 +85,12 @@ static grpc_core::OrphanablePtr<grpc_core::Resolver> build_fake_resolver(
grpc_core::ResolverArgs args;
args.args = &channel_args;
args.combiner = combiner;
args.result_handler = std::move(result_handler);
grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
factory->CreateResolver(args);
factory->CreateResolver(std::move(args));
return resolver;
}
typedef struct on_resolution_arg {
grpc_channel_args* resolver_result;
grpc_channel_args* expected_resolver_result;
gpr_event ev;
} on_resolution_arg;
// Callback to check the resolution result is as expected.
void on_resolution_cb(void* arg, grpc_error* error) {
if (error != GRPC_ERROR_NONE) return;
on_resolution_arg* res = static_cast<on_resolution_arg*>(arg);
// We only check the addresses channel arg because that's the only one
// explicitly set by the test via
// FakeResolverResponseGenerator::SetResponse().
const grpc_core::ServerAddressList* actual_addresses =
grpc_core::FindServerAddressListChannelArg(res->resolver_result);
const grpc_core::ServerAddressList* expected_addresses =
grpc_core::FindServerAddressListChannelArg(res->expected_resolver_result);
GPR_ASSERT(actual_addresses->size() == expected_addresses->size());
for (size_t i = 0; i < expected_addresses->size(); ++i) {
GPR_ASSERT((*actual_addresses)[i] == (*expected_addresses)[i]);
}
grpc_channel_args_destroy(res->resolver_result);
grpc_channel_args_destroy(res->expected_resolver_result);
gpr_event_set(&res->ev, (void*)1);
}
// Create a new resolution containing 2 addresses.
static grpc_channel_args* create_new_resolver_result() {
static size_t test_counter = 0;
@ -115,110 +130,99 @@ static grpc_channel_args* create_new_resolver_result() {
return results;
}
static on_resolution_arg create_on_resolution_arg(grpc_channel_args* results) {
on_resolution_arg on_res_arg;
memset(&on_res_arg, 0, sizeof(on_res_arg));
on_res_arg.expected_resolver_result = results;
gpr_event_init(&on_res_arg.ev);
return on_res_arg;
}
static void test_fake_resolver() {
grpc_core::ExecCtx exec_ctx;
grpc_combiner* combiner = grpc_combiner_create();
// Create resolver.
ResultHandler* result_handler = grpc_core::New<ResultHandler>();
grpc_core::RefCountedPtr<grpc_core::FakeResolverResponseGenerator>
response_generator =
grpc_core::MakeRefCounted<grpc_core::FakeResolverResponseGenerator>();
grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
build_fake_resolver(combiner, response_generator.get());
grpc_core::OrphanablePtr<grpc_core::Resolver> resolver = build_fake_resolver(
combiner, response_generator.get(),
grpc_core::UniquePtr<grpc_core::Resolver::ResultHandler>(result_handler));
GPR_ASSERT(resolver.get() != nullptr);
resolver->StartLocked();
// Test 1: normal resolution.
// next_results != NULL, reresolution_results == NULL.
// Expected response is next_results.
gpr_log(GPR_INFO, "TEST 1");
grpc_channel_args* results = create_new_resolver_result();
on_resolution_arg on_res_arg = create_on_resolution_arg(results);
grpc_closure* on_resolution = GRPC_CLOSURE_CREATE(
on_resolution_cb, &on_res_arg, grpc_combiner_scheduler(combiner));
// Resolution won't be triggered until next_results is set.
resolver->NextLocked(&on_res_arg.resolver_result, on_resolution);
gpr_event ev1;
gpr_event_init(&ev1);
result_handler->SetExpectedAndEvent(results, &ev1);
response_generator->SetResponse(results);
grpc_core::ExecCtx::Get()->Flush();
GPR_ASSERT(gpr_event_wait(&on_res_arg.ev,
grpc_timeout_seconds_to_deadline(5)) != nullptr);
GPR_ASSERT(gpr_event_wait(&ev1, grpc_timeout_seconds_to_deadline(5)) !=
nullptr);
grpc_channel_args_destroy(results);
// Test 2: update resolution.
// next_results != NULL, reresolution_results == NULL.
// Expected response is next_results.
gpr_log(GPR_INFO, "TEST 2");
results = create_new_resolver_result();
on_res_arg = create_on_resolution_arg(results);
on_resolution = GRPC_CLOSURE_CREATE(on_resolution_cb, &on_res_arg,
grpc_combiner_scheduler(combiner));
// Resolution won't be triggered until next_results is set.
resolver->NextLocked(&on_res_arg.resolver_result, on_resolution);
gpr_event ev2;
gpr_event_init(&ev2);
result_handler->SetExpectedAndEvent(results, &ev2);
response_generator->SetResponse(results);
grpc_core::ExecCtx::Get()->Flush();
GPR_ASSERT(gpr_event_wait(&on_res_arg.ev,
grpc_timeout_seconds_to_deadline(5)) != nullptr);
GPR_ASSERT(gpr_event_wait(&ev2, grpc_timeout_seconds_to_deadline(5)) !=
nullptr);
grpc_channel_args_destroy(results);
// Test 3: normal re-resolution.
// next_results == NULL, reresolution_results != NULL.
// Expected response is reresolution_results.
gpr_log(GPR_INFO, "TEST 3");
grpc_channel_args* reresolution_results = create_new_resolver_result();
on_res_arg =
create_on_resolution_arg(grpc_channel_args_copy(reresolution_results));
on_resolution = GRPC_CLOSURE_CREATE(on_resolution_cb, &on_res_arg,
grpc_combiner_scheduler(combiner));
resolver->NextLocked(&on_res_arg.resolver_result, on_resolution);
gpr_event ev3;
gpr_event_init(&ev3);
result_handler->SetExpectedAndEvent(reresolution_results, &ev3);
// Set reresolution_results.
// No result will be returned until re-resolution is requested.
response_generator->SetReresolutionResponse(reresolution_results);
// Flush here to guarantee that the response has been set.
grpc_core::ExecCtx::Get()->Flush();
// Trigger a re-resolution.
resolver->RequestReresolutionLocked();
grpc_core::ExecCtx::Get()->Flush();
GPR_ASSERT(gpr_event_wait(&on_res_arg.ev,
grpc_timeout_seconds_to_deadline(5)) != nullptr);
GPR_ASSERT(gpr_event_wait(&ev3, grpc_timeout_seconds_to_deadline(5)) !=
nullptr);
// Test 4: repeat re-resolution.
// next_results == NULL, reresolution_results != NULL.
// Expected response is reresolution_results.
on_res_arg = create_on_resolution_arg(reresolution_results);
on_resolution = GRPC_CLOSURE_CREATE(on_resolution_cb, &on_res_arg,
grpc_combiner_scheduler(combiner));
resolver->NextLocked(&on_res_arg.resolver_result, on_resolution);
gpr_log(GPR_INFO, "TEST 4");
gpr_event ev4;
gpr_event_init(&ev4);
result_handler->SetExpectedAndEvent(reresolution_results, &ev4);
// Trigger a re-resolution.
resolver->RequestReresolutionLocked();
grpc_core::ExecCtx::Get()->Flush();
GPR_ASSERT(gpr_event_wait(&on_res_arg.ev,
grpc_timeout_seconds_to_deadline(5)) != nullptr);
GPR_ASSERT(gpr_event_wait(&ev4, grpc_timeout_seconds_to_deadline(5)) !=
nullptr);
grpc_channel_args_destroy(reresolution_results);
// Test 5: normal resolution.
// next_results != NULL, reresolution_results != NULL.
// Expected response is next_results.
gpr_log(GPR_INFO, "TEST 5");
results = create_new_resolver_result();
on_res_arg = create_on_resolution_arg(results);
on_resolution = GRPC_CLOSURE_CREATE(on_resolution_cb, &on_res_arg,
grpc_combiner_scheduler(combiner));
// Resolution won't be triggered until next_results is set.
resolver->NextLocked(&on_res_arg.resolver_result, on_resolution);
gpr_event ev5;
gpr_event_init(&ev5);
result_handler->SetExpectedAndEvent(results, &ev5);
response_generator->SetResponse(results);
grpc_core::ExecCtx::Get()->Flush();
GPR_ASSERT(gpr_event_wait(&on_res_arg.ev,
grpc_timeout_seconds_to_deadline(5)) != nullptr);
GPR_ASSERT(gpr_event_wait(&ev5, grpc_timeout_seconds_to_deadline(5)) !=
nullptr);
grpc_channel_args_destroy(results);
// Test 6: no-op.
// Requesting a new resolution without setting the response shouldn't trigger
// the resolution callback.
memset(&on_res_arg, 0, sizeof(on_res_arg));
on_resolution = GRPC_CLOSURE_CREATE(on_resolution_cb, &on_res_arg,
grpc_combiner_scheduler(combiner));
resolver->NextLocked(&on_res_arg.resolver_result, on_resolution);
grpc_core::ExecCtx::Get()->Flush();
GPR_ASSERT(gpr_event_wait(&on_res_arg.ev,
grpc_timeout_milliseconds_to_deadline(100)) ==
gpr_log(GPR_INFO, "TEST 6");
gpr_event ev6;
gpr_event_init(&ev6);
result_handler->SetExpectedAndEvent(nullptr, &ev6);
GPR_ASSERT(gpr_event_wait(&ev6, grpc_timeout_milliseconds_to_deadline(100)) ==
nullptr);
// Clean up.
// Note: Need to explicitly unref the resolver and flush the exec_ctx
// to make sure that the final resolver callback (with error set to
// "Resolver Shutdown") is invoked before on_res_arg goes out of scope.
resolver.reset();
grpc_core::ExecCtx::Get()->Flush();
GRPC_COMBINER_UNREF(combiner, "test_fake_resolver");
}

@ -30,15 +30,14 @@
static grpc_combiner* g_combiner;
typedef struct on_resolution_arg {
char* expected_server_name;
grpc_channel_args* resolver_result;
} on_resolution_arg;
void on_resolution_cb(void* arg, grpc_error* error) {
on_resolution_arg* res = static_cast<on_resolution_arg*>(arg);
grpc_channel_args_destroy(res->resolver_result);
}
class ResultHandler : public grpc_core::Resolver::ResultHandler {
public:
void ReturnResult(const grpc_channel_args* args) override {
grpc_channel_args_destroy(args);
}
void ReturnError(grpc_error* error) override { GRPC_ERROR_UNREF(error); }
};
static void test_succeeds(grpc_core::ResolverFactory* factory,
const char* string) {
@ -50,18 +49,14 @@ static void test_succeeds(grpc_core::ResolverFactory* factory,
grpc_core::ResolverArgs args;
args.uri = uri;
args.combiner = g_combiner;
args.result_handler =
grpc_core::UniquePtr<grpc_core::Resolver::ResultHandler>(
grpc_core::New<ResultHandler>());
grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
factory->CreateResolver(args);
factory->CreateResolver(std::move(args));
GPR_ASSERT(resolver != nullptr);
on_resolution_arg on_res_arg;
memset(&on_res_arg, 0, sizeof(on_res_arg));
on_res_arg.expected_server_name = uri->path;
grpc_closure* on_resolution = GRPC_CLOSURE_CREATE(
on_resolution_cb, &on_res_arg, grpc_schedule_on_exec_ctx);
resolver->NextLocked(&on_res_arg.resolver_result, on_resolution);
grpc_uri_destroy(uri);
resolver->StartLocked();
/* Flush ExecCtx to avoid stack-use-after-scope on on_res_arg which is
* accessed in the closure on_resolution_cb */
grpc_core::ExecCtx::Get()->Flush();
@ -77,8 +72,11 @@ static void test_fails(grpc_core::ResolverFactory* factory,
grpc_core::ResolverArgs args;
args.uri = uri;
args.combiner = g_combiner;
args.result_handler =
grpc_core::UniquePtr<grpc_core::Resolver::ResultHandler>(
grpc_core::New<ResultHandler>());
grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
factory->CreateResolver(args);
factory->CreateResolver(std::move(args));
GPR_ASSERT(resolver == nullptr);
grpc_uri_destroy(uri);
}

@ -894,9 +894,7 @@ TEST_F(ClientGlobalInterceptorEnd2endTest, DummyGlobalInterceptor) {
MakeCall(channel);
// Make sure all 20 dummy interceptors were run with the global interceptor
EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 21);
// Reset the global interceptor. This is again 'safe' because there are no
// other ongoing gRPC operations
experimental::RegisterGlobalClientInterceptorFactory(nullptr);
experimental::TestOnlyResetGlobalClientInterceptorFactory();
}
TEST_F(ClientGlobalInterceptorEnd2endTest, LoggingGlobalInterceptor) {
@ -920,9 +918,7 @@ TEST_F(ClientGlobalInterceptorEnd2endTest, LoggingGlobalInterceptor) {
MakeCall(channel);
// Make sure all 20 dummy interceptors were run
EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20);
// Reset the global interceptor. This is again 'safe' because there are no
// other ongoing gRPC operations
experimental::RegisterGlobalClientInterceptorFactory(nullptr);
experimental::TestOnlyResetGlobalClientInterceptorFactory();
}
TEST_F(ClientGlobalInterceptorEnd2endTest, HijackingGlobalInterceptor) {
@ -946,9 +942,7 @@ TEST_F(ClientGlobalInterceptorEnd2endTest, HijackingGlobalInterceptor) {
MakeCall(channel);
// Make sure all 20 dummy interceptors were run
EXPECT_EQ(DummyInterceptor::GetNumTimesRun(), 20);
// Reset the global interceptor. This is again 'safe' because there are no
// other ongoing gRPC operations
experimental::RegisterGlobalClientInterceptorFactory(nullptr);
experimental::TestOnlyResetGlobalClientInterceptorFactory();
}
} // namespace

@ -160,14 +160,27 @@ void PollPollsetUntilRequestDone(ArgsStruct* args) {
}
}
void CheckResolverResultAssertFailureLocked(void* arg, grpc_error* error) {
EXPECT_NE(error, GRPC_ERROR_NONE);
ArgsStruct* args = static_cast<ArgsStruct*>(arg);
gpr_atm_rel_store(&args->done_atm, 1);
gpr_mu_lock(args->mu);
GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(args->pollset, nullptr));
gpr_mu_unlock(args->mu);
}
class AssertFailureResultHandler : public grpc_core::Resolver::ResultHandler {
public:
explicit AssertFailureResultHandler(ArgsStruct* args) : args_(args) {}
~AssertFailureResultHandler() override {
gpr_atm_rel_store(&args_->done_atm, 1);
gpr_mu_lock(args_->mu);
GRPC_LOG_IF_ERROR("pollset_kick",
grpc_pollset_kick(args_->pollset, nullptr));
gpr_mu_unlock(args_->mu);
}
void ReturnResult(const grpc_channel_args* args) override {
GPR_ASSERT(false);
}
void ReturnError(grpc_error* error) override { GPR_ASSERT(false); }
private:
ArgsStruct* args_;
};
void TestCancelActiveDNSQuery(ArgsStruct* args) {
int fake_dns_port = grpc_pick_unused_port_or_die();
@ -180,13 +193,11 @@ void TestCancelActiveDNSQuery(ArgsStruct* args) {
// create resolver and resolve
grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
grpc_core::ResolverRegistry::CreateResolver(
client_target, nullptr, args->pollset_set, args->lock);
client_target, nullptr, args->pollset_set, args->lock,
grpc_core::UniquePtr<grpc_core::Resolver::ResultHandler>(
grpc_core::New<AssertFailureResultHandler>(args)));
gpr_free(client_target);
grpc_closure on_resolver_result_changed;
GRPC_CLOSURE_INIT(&on_resolver_result_changed,
CheckResolverResultAssertFailureLocked, (void*)args,
grpc_combiner_scheduler(args->lock));
resolver->NextLocked(&args->channel_args, &on_resolver_result_changed);
resolver->StartLocked();
// Without resetting and causing resolver shutdown, the
// PollPollsetUntilRequestDone call should never finish.
resolver.reset();

@ -239,7 +239,7 @@ void PollPollsetUntilRequestDone(ArgsStruct* args) {
gpr_event_set(&args->ev, (void*)1);
}
void CheckServiceConfigResultLocked(grpc_channel_args* channel_args,
void CheckServiceConfigResultLocked(const grpc_channel_args* channel_args,
ArgsStruct* args) {
const grpc_arg* service_config_arg =
grpc_channel_args_find(channel_args, GRPC_ARG_SERVICE_CONFIG);
@ -253,7 +253,7 @@ void CheckServiceConfigResultLocked(grpc_channel_args* channel_args,
}
}
void CheckLBPolicyResultLocked(grpc_channel_args* channel_args,
void CheckLBPolicyResultLocked(const grpc_channel_args* channel_args,
ArgsStruct* args) {
const grpc_arg* lb_policy_arg =
grpc_channel_args_find(channel_args, GRPC_ARG_LB_POLICY_NAME);
@ -394,54 +394,86 @@ void OpenAndCloseSocketsStressLoop(int dummy_port, gpr_event* done_ev) {
}
#endif
void CheckResolverResultLocked(void* argsp, grpc_error* err) {
EXPECT_EQ(err, GRPC_ERROR_NONE);
ArgsStruct* args = (ArgsStruct*)argsp;
grpc_channel_args* channel_args = args->channel_args;
grpc_core::ServerAddressList* addresses =
grpc_core::FindServerAddressListChannelArg(channel_args);
gpr_log(GPR_INFO, "num addrs found: %" PRIdPTR ". expected %" PRIdPTR,
addresses->size(), args->expected_addrs.size());
GPR_ASSERT(addresses->size() == args->expected_addrs.size());
std::vector<GrpcLBAddress> found_lb_addrs;
for (size_t i = 0; i < addresses->size(); i++) {
grpc_core::ServerAddress& addr = (*addresses)[i];
char* str;
grpc_sockaddr_to_string(&str, &addr.address(), 1 /* normalize */);
gpr_log(GPR_INFO, "%s", str);
found_lb_addrs.emplace_back(
GrpcLBAddress(std::string(str), addr.IsBalancer()));
gpr_free(str);
class ResultHandler : public grpc_core::Resolver::ResultHandler {
public:
static grpc_core::UniquePtr<grpc_core::Resolver::ResultHandler> Create(
ArgsStruct* args) {
return grpc_core::UniquePtr<grpc_core::Resolver::ResultHandler>(
grpc_core::New<ResultHandler>(args));
}
if (args->expected_addrs.size() != found_lb_addrs.size()) {
gpr_log(GPR_DEBUG,
"found lb addrs size is: %" PRIdPTR
". expected addrs size is %" PRIdPTR,
found_lb_addrs.size(), args->expected_addrs.size());
abort();
explicit ResultHandler(ArgsStruct* args) : args_(args) {}
void ReturnResult(const grpc_channel_args* result) override {
CheckResult(result);
gpr_atm_rel_store(&args_->done_atm, 1);
gpr_mu_lock(args_->mu);
GRPC_LOG_IF_ERROR("pollset_kick",
grpc_pollset_kick(args_->pollset, nullptr));
gpr_mu_unlock(args_->mu);
grpc_channel_args_destroy(result);
}
EXPECT_THAT(args->expected_addrs, UnorderedElementsAreArray(found_lb_addrs));
CheckServiceConfigResultLocked(channel_args, args);
if (args->expected_service_config_string == "") {
CheckLBPolicyResultLocked(channel_args, args);
void ReturnError(grpc_error* error) override {
gpr_log(GPR_ERROR, "resolver returned error: %s", grpc_error_string(error));
GPR_ASSERT(false);
}
gpr_atm_rel_store(&args->done_atm, 1);
gpr_mu_lock(args->mu);
GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(args->pollset, nullptr));
gpr_mu_unlock(args->mu);
}
void CheckResolvedWithoutErrorLocked(void* argsp, grpc_error* err) {
EXPECT_EQ(err, GRPC_ERROR_NONE);
ArgsStruct* args = (ArgsStruct*)argsp;
gpr_atm_rel_store(&args->done_atm, 1);
gpr_mu_lock(args->mu);
GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(args->pollset, nullptr));
gpr_mu_unlock(args->mu);
}
virtual void CheckResult(const grpc_channel_args* channel_args) {}
protected:
ArgsStruct* args_struct() const { return args_; }
private:
ArgsStruct* args_;
};
class CheckingResultHandler : public ResultHandler {
public:
static grpc_core::UniquePtr<grpc_core::Resolver::ResultHandler> Create(
ArgsStruct* args) {
return grpc_core::UniquePtr<grpc_core::Resolver::ResultHandler>(
grpc_core::New<CheckingResultHandler>(args));
}
explicit CheckingResultHandler(ArgsStruct* args) : ResultHandler(args) {}
void CheckResult(const grpc_channel_args* channel_args) override {
ArgsStruct* args = args_struct();
grpc_core::ServerAddressList* addresses =
grpc_core::FindServerAddressListChannelArg(channel_args);
gpr_log(GPR_INFO, "num addrs found: %" PRIdPTR ". expected %" PRIdPTR,
addresses->size(), args->expected_addrs.size());
GPR_ASSERT(addresses->size() == args->expected_addrs.size());
std::vector<GrpcLBAddress> found_lb_addrs;
for (size_t i = 0; i < addresses->size(); i++) {
grpc_core::ServerAddress& addr = (*addresses)[i];
char* str;
grpc_sockaddr_to_string(&str, &addr.address(), 1 /* normalize */);
gpr_log(GPR_INFO, "%s", str);
found_lb_addrs.emplace_back(
GrpcLBAddress(std::string(str), addr.IsBalancer()));
gpr_free(str);
}
if (args->expected_addrs.size() != found_lb_addrs.size()) {
gpr_log(GPR_DEBUG,
"found lb addrs size is: %" PRIdPTR
". expected addrs size is %" PRIdPTR,
found_lb_addrs.size(), args->expected_addrs.size());
abort();
}
EXPECT_THAT(args->expected_addrs,
UnorderedElementsAreArray(found_lb_addrs));
CheckServiceConfigResultLocked(channel_args, args);
if (args->expected_service_config_string == "") {
CheckLBPolicyResultLocked(channel_args, args);
}
}
};
void RunResolvesRelevantRecordsTest(void (*OnDoneLocked)(void* arg,
grpc_error* error)) {
void RunResolvesRelevantRecordsTest(
grpc_core::UniquePtr<grpc_core::Resolver::ResultHandler> (
*CreateResultHandler)(ArgsStruct* args)) {
grpc_core::ExecCtx exec_ctx;
ArgsStruct args;
ArgsInit(&args);
@ -491,20 +523,18 @@ void RunResolvesRelevantRecordsTest(void (*OnDoneLocked)(void* arg,
// create resolver and resolve
grpc_core::OrphanablePtr<grpc_core::Resolver> resolver =
grpc_core::ResolverRegistry::CreateResolver(whole_uri, resolver_args,
args.pollset_set, args.lock);
args.pollset_set, args.lock,
CreateResultHandler(&args));
grpc_channel_args_destroy(resolver_args);
gpr_free(whole_uri);
grpc_closure on_resolver_result_changed;
GRPC_CLOSURE_INIT(&on_resolver_result_changed, OnDoneLocked, (void*)&args,
grpc_combiner_scheduler(args.lock));
resolver->NextLocked(&args.channel_args, &on_resolver_result_changed);
resolver->StartLocked();
grpc_core::ExecCtx::Get()->Flush();
PollPollsetUntilRequestDone(&args);
ArgsFinish(&args);
}
TEST(ResolverComponentTest, TestResolvesRelevantRecords) {
RunResolvesRelevantRecordsTest(CheckResolverResultLocked);
RunResolvesRelevantRecordsTest(CheckingResultHandler::Create);
}
TEST(ResolverComponentTest, TestResolvesRelevantRecordsWithConcurrentFdStress) {
@ -515,7 +545,7 @@ TEST(ResolverComponentTest, TestResolvesRelevantRecordsWithConcurrentFdStress) {
std::thread socket_stress_thread(OpenAndCloseSocketsStressLoop, dummy_port,
&done_ev);
// Run the resolver test
RunResolvesRelevantRecordsTest(CheckResolvedWithoutErrorLocked);
RunResolvesRelevantRecordsTest(ResultHandler::Create);
// Shutdown and join stress thread
gpr_event_set(&done_ev, (void*)1);
socket_stress_thread.join();

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -71,6 +71,12 @@ _SKIP_GOOGLE_DEFAULT_CREDS = [
_GOOGLE_DEFAULT_CREDS_TEST_CASE,
]
_COMPUTE_ENGINE_CHANNEL_CREDS_TEST_CASE = 'compute_engine_channel_credentials'
_SKIP_COMPUTE_ENGINE_CHANNEL_CREDS = [
_COMPUTE_ENGINE_CHANNEL_CREDS_TEST_CASE,
]
_TEST_TIMEOUT = 3 * 60
# disable this test on core-based languages,
@ -106,7 +112,9 @@ class CXXLanguage:
return {}
def unimplemented_test_cases(self):
return _SKIP_DATA_FRAME_PADDING + _SKIP_SPECIAL_STATUS_MESSAGE
return _SKIP_DATA_FRAME_PADDING + \
_SKIP_SPECIAL_STATUS_MESSAGE + \
_SKIP_COMPUTE_ENGINE_CHANNEL_CREDS
def unimplemented_test_cases_server(self):
return []
@ -135,7 +143,11 @@ class CSharpLanguage:
return {}
def unimplemented_test_cases(self):
return _SKIP_SERVER_COMPRESSION + _SKIP_DATA_FRAME_PADDING + _SKIP_SPECIAL_STATUS_MESSAGE + _SKIP_GOOGLE_DEFAULT_CREDS
return _SKIP_SERVER_COMPRESSION + \
_SKIP_DATA_FRAME_PADDING + \
_SKIP_SPECIAL_STATUS_MESSAGE + \
_SKIP_GOOGLE_DEFAULT_CREDS + \
_SKIP_COMPUTE_ENGINE_CHANNEL_CREDS
def unimplemented_test_cases_server(self):
return _SKIP_COMPRESSION
@ -164,7 +176,11 @@ class CSharpCoreCLRLanguage:
return {}
def unimplemented_test_cases(self):
return _SKIP_SERVER_COMPRESSION + _SKIP_DATA_FRAME_PADDING + _SKIP_SPECIAL_STATUS_MESSAGE + _SKIP_GOOGLE_DEFAULT_CREDS
return _SKIP_SERVER_COMPRESSION + \
_SKIP_DATA_FRAME_PADDING + \
_SKIP_SPECIAL_STATUS_MESSAGE + \
_SKIP_GOOGLE_DEFAULT_CREDS + \
_SKIP_COMPUTE_ENGINE_CHANNEL_CREDS
def unimplemented_test_cases_server(self):
return _SKIP_COMPRESSION
@ -225,7 +241,10 @@ class DartLanguage:
return {}
def unimplemented_test_cases(self):
return _SKIP_COMPRESSION + _SKIP_SPECIAL_STATUS_MESSAGE + _SKIP_GOOGLE_DEFAULT_CREDS
return _SKIP_COMPRESSION + \
_SKIP_SPECIAL_STATUS_MESSAGE + \
_SKIP_GOOGLE_DEFAULT_CREDS + \
_SKIP_COMPUTE_ENGINE_CHANNEL_CREDS
def unimplemented_test_cases_server(self):
return _SKIP_COMPRESSION + _SKIP_SPECIAL_STATUS_MESSAGE
@ -316,7 +335,7 @@ class GoLanguage:
return {}
def unimplemented_test_cases(self):
return _SKIP_COMPRESSION
return _SKIP_COMPRESSION + _SKIP_COMPUTE_ENGINE_CHANNEL_CREDS
def unimplemented_test_cases_server(self):
return _SKIP_COMPRESSION
@ -346,7 +365,11 @@ class Http2Server:
return {}
def unimplemented_test_cases(self):
return _TEST_CASES + _SKIP_DATA_FRAME_PADDING + _SKIP_SPECIAL_STATUS_MESSAGE + _SKIP_GOOGLE_DEFAULT_CREDS
return _TEST_CASES + \
_SKIP_DATA_FRAME_PADDING + \
_SKIP_SPECIAL_STATUS_MESSAGE + \
_SKIP_GOOGLE_DEFAULT_CREDS + \
_SKIP_COMPUTE_ENGINE_CHANNEL_CREDS
def unimplemented_test_cases_server(self):
return _TEST_CASES
@ -376,7 +399,10 @@ class Http2Client:
return {}
def unimplemented_test_cases(self):
return _TEST_CASES + _SKIP_SPECIAL_STATUS_MESSAGE + _SKIP_GOOGLE_DEFAULT_CREDS
return _TEST_CASES + \
_SKIP_SPECIAL_STATUS_MESSAGE + \
_SKIP_GOOGLE_DEFAULT_CREDS + \
_SKIP_COMPUTE_ENGINE_CHANNEL_CREDS
def unimplemented_test_cases_server(self):
return _TEST_CASES
@ -413,7 +439,10 @@ class NodeLanguage:
return {}
def unimplemented_test_cases(self):
return _SKIP_COMPRESSION + _SKIP_DATA_FRAME_PADDING + _SKIP_GOOGLE_DEFAULT_CREDS
return _SKIP_COMPRESSION + \
_SKIP_DATA_FRAME_PADDING + \
_SKIP_GOOGLE_DEFAULT_CREDS + \
_SKIP_COMPUTE_ENGINE_CHANNEL_CREDS
def unimplemented_test_cases_server(self):
return _SKIP_COMPRESSION
@ -443,7 +472,10 @@ class NodePureJSLanguage:
return {}
def unimplemented_test_cases(self):
return _SKIP_COMPRESSION + _SKIP_DATA_FRAME_PADDING + _SKIP_GOOGLE_DEFAULT_CREDS
return _SKIP_COMPRESSION + \
_SKIP_DATA_FRAME_PADDING + \
_SKIP_GOOGLE_DEFAULT_CREDS + \
_SKIP_COMPUTE_ENGINE_CHANNEL_CREDS
def unimplemented_test_cases_server(self):
return []
@ -468,7 +500,11 @@ class PHPLanguage:
return {}
def unimplemented_test_cases(self):
return _SKIP_COMPRESSION + _SKIP_DATA_FRAME_PADDING + _SKIP_SPECIAL_STATUS_MESSAGE + _SKIP_GOOGLE_DEFAULT_CREDS
return _SKIP_COMPRESSION + \
_SKIP_DATA_FRAME_PADDING + \
_SKIP_SPECIAL_STATUS_MESSAGE + \
_SKIP_GOOGLE_DEFAULT_CREDS + \
_SKIP_COMPUTE_ENGINE_CHANNEL_CREDS
def unimplemented_test_cases_server(self):
return []
@ -493,7 +529,11 @@ class PHP7Language:
return {}
def unimplemented_test_cases(self):
return _SKIP_COMPRESSION + _SKIP_DATA_FRAME_PADDING + _SKIP_SPECIAL_STATUS_MESSAGE + _SKIP_GOOGLE_DEFAULT_CREDS
return _SKIP_COMPRESSION + \
_SKIP_DATA_FRAME_PADDING + \
_SKIP_SPECIAL_STATUS_MESSAGE + \
_SKIP_GOOGLE_DEFAULT_CREDS + \
_SKIP_COMPUTE_ENGINE_CHANNEL_CREDS
def unimplemented_test_cases_server(self):
return []
@ -528,7 +568,12 @@ class ObjcLanguage:
# cmdline argument. Here we return all but one test cases as unimplemented,
# and depend upon ObjC test's behavior that it runs all cases even when
# we tell it to run just one.
return _TEST_CASES[1:] + _SKIP_COMPRESSION + _SKIP_DATA_FRAME_PADDING + _SKIP_SPECIAL_STATUS_MESSAGE + _SKIP_GOOGLE_DEFAULT_CREDS
return _TEST_CASES[1:] + \
_SKIP_COMPRESSION + \
_SKIP_DATA_FRAME_PADDING + \
_SKIP_SPECIAL_STATUS_MESSAGE + \
_SKIP_GOOGLE_DEFAULT_CREDS + \
_SKIP_COMPUTE_ENGINE_CHANNEL_CREDS
def unimplemented_test_cases_server(self):
return _SKIP_COMPRESSION
@ -563,7 +608,11 @@ class RubyLanguage:
return {}
def unimplemented_test_cases(self):
return _SKIP_SERVER_COMPRESSION + _SKIP_DATA_FRAME_PADDING + _SKIP_SPECIAL_STATUS_MESSAGE + _SKIP_GOOGLE_DEFAULT_CREDS
return _SKIP_SERVER_COMPRESSION + \
_SKIP_DATA_FRAME_PADDING + \
_SKIP_SPECIAL_STATUS_MESSAGE + \
_SKIP_GOOGLE_DEFAULT_CREDS + \
_SKIP_COMPUTE_ENGINE_CHANNEL_CREDS
def unimplemented_test_cases_server(self):
return _SKIP_COMPRESSION
@ -608,7 +657,10 @@ class PythonLanguage:
}
def unimplemented_test_cases(self):
return _SKIP_COMPRESSION + _SKIP_DATA_FRAME_PADDING + _SKIP_GOOGLE_DEFAULT_CREDS
return _SKIP_COMPRESSION + \
_SKIP_DATA_FRAME_PADDING + \
_SKIP_GOOGLE_DEFAULT_CREDS + \
_SKIP_COMPUTE_ENGINE_CHANNEL_CREDS
def unimplemented_test_cases_server(self):
return _SKIP_COMPRESSION
@ -657,6 +709,7 @@ _AUTH_TEST_CASES = [
'oauth2_auth_token',
'per_rpc_creds',
_GOOGLE_DEFAULT_CREDS_TEST_CASE,
_COMPUTE_ENGINE_CHANNEL_CREDS_TEST_CASE,
]
_HTTP2_TEST_CASES = ['tls', 'framing']
@ -682,9 +735,7 @@ _LANGUAGES_FOR_ALTS_TEST_CASES = ['java', 'go', 'c++']
_SERVERS_FOR_ALTS_TEST_CASES = ['java', 'go', 'c++']
_TRANSPORT_SECURITY_OPTIONS = [
'tls', 'alts', 'google_default_credentials', 'insecure'
]
_TRANSPORT_SECURITY_OPTIONS = ['tls', 'alts', 'insecure']
DOCKER_WORKDIR_ROOT = '/var/local/git/grpc'
@ -796,6 +847,9 @@ def auth_options(language,
env['GOOGLE_APPLICATION_CREDENTIALS'] = service_account_key_file
cmdargs += [default_account_arg]
if test_case == _COMPUTE_ENGINE_CHANNEL_CREDS_TEST_CASE:
cmdargs += [default_account_arg]
return (cmdargs, env)
@ -832,9 +886,15 @@ def cloud_to_prod_jobspec(language,
transport_security_options = [
'--custom_credentials_type=google_default_credentials'
]
elif transport_security == 'compute_engine_channel_creds' and str(
language) in ['java', 'javaokhttp']:
transport_security_options = [
'--custom_credentials_type=compute_engine_channel_creds'
]
else:
print('Invalid transport security option %s in cloud_to_prod_jobspec.' %
transport_security)
print(
'Invalid transport security option %s in cloud_to_prod_jobspec. Lang: %s'
% (str(language), transport_security))
sys.exit(1)
cmdargs = cmdargs + transport_security_options
environ = dict(language.cloud_to_prod_env(), **language.global_env())
@ -1367,10 +1427,8 @@ try:
jobs = []
if args.cloud_to_prod:
if args.transport_security not in ['tls', 'google_default_credentials']:
print(
'TLS or google default credential is always enabled for cloud_to_prod scenarios.'
)
if args.transport_security not in ['tls']:
print('TLS is always enabled for cloud_to_prod scenarios.')
for server_host_nickname in args.prod_servers:
for language in languages:
for test_case in _TEST_CASES:
@ -1407,6 +1465,23 @@ try:
transport_security=
'google_default_credentials')
jobs.append(google_default_creds_test_job)
if str(language) in ['java', 'javaokhttp']:
compute_engine_channel_creds_test_job = cloud_to_prod_jobspec(
language,
test_case,
server_host_nickname,
prod_servers[server_host_nickname],
google_default_creds_use_key_file=args.
google_default_creds_use_key_file,
docker_image=docker_images.get(
str(language)),
manual_cmd_log=client_manual_cmd_log,
service_account_key_file=args.
service_account_key_file,
transport_security=
'compute_engine_channel_creds')
jobs.append(
compute_engine_channel_creds_test_job)
if args.http2_interop:
for test_case in _HTTP2_TEST_CASES:
@ -1424,10 +1499,8 @@ try:
jobs.append(test_job)
if args.cloud_to_prod_auth:
if args.transport_security not in ['tls', 'google_default_credentials']:
print(
'TLS or google default credential is always enabled for cloud_to_prod scenarios.'
)
if args.transport_security not in ['tls']:
print('TLS is always enabled for cloud_to_prod scenarios.')
for server_host_nickname in args.prod_servers:
for language in languages:
for test_case in _AUTH_TEST_CASES:
@ -1435,9 +1508,12 @@ try:
not compute_engine_creds_required(
language, test_case)):
if not test_case in language.unimplemented_test_cases():
transport_security = 'tls'
if test_case == _GOOGLE_DEFAULT_CREDS_TEST_CASE:
transport_security = 'google_default_credentials'
elif test_case == _COMPUTE_ENGINE_CHANNEL_CREDS_TEST_CASE:
transport_security = 'compute_engine_channel_creds'
else:
transport_security = 'tls'
test_job = cloud_to_prod_jobspec(
language,
test_case,

Loading…
Cancel
Save