diff --git a/BUILD b/BUILD index aabfe01e207..a26e6d1f513 100644 --- a/BUILD +++ b/BUILD @@ -225,6 +225,7 @@ GRPCXX_PUBLIC_HDRS = [ "include/grpcpp/ext/health_check_service_server_builder_option.h", "include/grpcpp/generic/async_generic_service.h", "include/grpcpp/generic/generic_stub.h", + "include/grpcpp/generic/generic_stub_impl.h", "include/grpcpp/grpcpp.h", "include/grpcpp/health_check_service_interface.h", "include/grpcpp/health_check_service_interface_impl.h", @@ -252,6 +253,7 @@ GRPCXX_PUBLIC_HDRS = [ "include/grpcpp/security/auth_metadata_processor_impl.h", "include/grpcpp/security/credentials.h", "include/grpcpp/security/server_credentials.h", + "include/grpcpp/security/server_credentials_impl.h", "include/grpcpp/server.h", "include/grpcpp/server_impl.h", "include/grpcpp/server_builder.h", @@ -2198,6 +2200,7 @@ grpc_cc_library( public_hdrs = [ "include/grpc++/ext/proto_server_reflection_plugin.h", "include/grpcpp/ext/proto_server_reflection_plugin.h", + "include/grpcpp/ext/proto_server_reflection_plugin_impl.h", ], deps = [ ":grpc++", diff --git a/BUILD.gn b/BUILD.gn index 5b0677023dd..8fed27e202e 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1012,6 +1012,7 @@ config("grpc_config") { "include/grpcpp/ext/health_check_service_server_builder_option.h", "include/grpcpp/generic/async_generic_service.h", "include/grpcpp/generic/generic_stub.h", + "include/grpcpp/generic/generic_stub_impl.h", "include/grpcpp/grpcpp.h", "include/grpcpp/health_check_service_interface.h", "include/grpcpp/health_check_service_interface_impl.h", @@ -1083,6 +1084,7 @@ config("grpc_config") { "include/grpcpp/security/auth_metadata_processor_impl.h", "include/grpcpp/security/credentials.h", "include/grpcpp/security/server_credentials.h", + "include/grpcpp/security/server_credentials_impl.h", "include/grpcpp/server.h", "include/grpcpp/server_builder.h", "include/grpcpp/server_context.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index 50d69f90388..a84523e5c92 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3006,6 +3006,7 @@ foreach(_hdr include/grpcpp/ext/health_check_service_server_builder_option.h include/grpcpp/generic/async_generic_service.h include/grpcpp/generic/generic_stub.h + include/grpcpp/generic/generic_stub_impl.h include/grpcpp/grpcpp.h include/grpcpp/health_check_service_interface.h include/grpcpp/health_check_service_interface_impl.h @@ -3031,6 +3032,7 @@ foreach(_hdr include/grpcpp/security/auth_metadata_processor_impl.h include/grpcpp/security/credentials.h include/grpcpp/security/server_credentials.h + include/grpcpp/security/server_credentials_impl.h include/grpcpp/server.h include/grpcpp/server_builder.h include/grpcpp/server_context.h @@ -3605,6 +3607,7 @@ foreach(_hdr include/grpcpp/ext/health_check_service_server_builder_option.h include/grpcpp/generic/async_generic_service.h include/grpcpp/generic/generic_stub.h + include/grpcpp/generic/generic_stub_impl.h include/grpcpp/grpcpp.h include/grpcpp/health_check_service_interface.h include/grpcpp/health_check_service_interface_impl.h @@ -3630,6 +3633,7 @@ foreach(_hdr include/grpcpp/security/auth_metadata_processor_impl.h include/grpcpp/security/credentials.h include/grpcpp/security/server_credentials.h + include/grpcpp/security/server_credentials_impl.h include/grpcpp/server.h include/grpcpp/server_builder.h include/grpcpp/server_context.h @@ -3976,6 +3980,7 @@ target_link_libraries(grpc++_reflection foreach(_hdr include/grpc++/ext/proto_server_reflection_plugin.h include/grpcpp/ext/proto_server_reflection_plugin.h + include/grpcpp/ext/proto_server_reflection_plugin_impl.h ) string(REPLACE "include/" "" _path ${_hdr}) get_filename_component(_path ${_path} PATH) @@ -4577,6 +4582,7 @@ foreach(_hdr include/grpcpp/ext/health_check_service_server_builder_option.h include/grpcpp/generic/async_generic_service.h include/grpcpp/generic/generic_stub.h + include/grpcpp/generic/generic_stub_impl.h include/grpcpp/grpcpp.h include/grpcpp/health_check_service_interface.h include/grpcpp/health_check_service_interface_impl.h @@ -4602,6 +4608,7 @@ foreach(_hdr include/grpcpp/security/auth_metadata_processor_impl.h include/grpcpp/security/credentials.h include/grpcpp/security/server_credentials.h + include/grpcpp/security/server_credentials_impl.h include/grpcpp/server.h include/grpcpp/server_builder.h include/grpcpp/server_context.h diff --git a/Makefile b/Makefile index 3ecbf182393..d1158bf31ba 100644 --- a/Makefile +++ b/Makefile @@ -5337,6 +5337,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/ext/health_check_service_server_builder_option.h \ include/grpcpp/generic/async_generic_service.h \ include/grpcpp/generic/generic_stub.h \ + include/grpcpp/generic/generic_stub_impl.h \ include/grpcpp/grpcpp.h \ include/grpcpp/health_check_service_interface.h \ include/grpcpp/health_check_service_interface_impl.h \ @@ -5362,6 +5363,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/security/auth_metadata_processor_impl.h \ include/grpcpp/security/credentials.h \ include/grpcpp/security/server_credentials.h \ + include/grpcpp/security/server_credentials_impl.h \ include/grpcpp/server.h \ include/grpcpp/server_builder.h \ include/grpcpp/server_context.h \ @@ -5944,6 +5946,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/ext/health_check_service_server_builder_option.h \ include/grpcpp/generic/async_generic_service.h \ include/grpcpp/generic/generic_stub.h \ + include/grpcpp/generic/generic_stub_impl.h \ include/grpcpp/grpcpp.h \ include/grpcpp/health_check_service_interface.h \ include/grpcpp/health_check_service_interface_impl.h \ @@ -5969,6 +5972,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/security/auth_metadata_processor_impl.h \ include/grpcpp/security/credentials.h \ include/grpcpp/security/server_credentials.h \ + include/grpcpp/security/server_credentials_impl.h \ include/grpcpp/server.h \ include/grpcpp/server_builder.h \ include/grpcpp/server_context.h \ @@ -6314,6 +6318,7 @@ LIBGRPC++_REFLECTION_SRC = \ PUBLIC_HEADERS_CXX += \ include/grpc++/ext/proto_server_reflection_plugin.h \ include/grpcpp/ext/proto_server_reflection_plugin.h \ + include/grpcpp/ext/proto_server_reflection_plugin_impl.h \ LIBGRPC++_REFLECTION_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC++_REFLECTION_SRC)))) @@ -6865,6 +6870,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/ext/health_check_service_server_builder_option.h \ include/grpcpp/generic/async_generic_service.h \ include/grpcpp/generic/generic_stub.h \ + include/grpcpp/generic/generic_stub_impl.h \ include/grpcpp/grpcpp.h \ include/grpcpp/health_check_service_interface.h \ include/grpcpp/health_check_service_interface_impl.h \ @@ -6890,6 +6896,7 @@ PUBLIC_HEADERS_CXX += \ include/grpcpp/security/auth_metadata_processor_impl.h \ include/grpcpp/security/credentials.h \ include/grpcpp/security/server_credentials.h \ + include/grpcpp/security/server_credentials_impl.h \ include/grpcpp/server.h \ include/grpcpp/server_builder.h \ include/grpcpp/server_context.h \ diff --git a/WORKSPACE b/WORKSPACE index 81371bf4187..18f389edd24 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -17,20 +17,13 @@ register_toolchains( "//third_party/toolchains:cc-toolchain-clang-x86_64-default", ) -http_archive( - name = "cython", - build_file = "//third_party:cython.BUILD", - sha256 = "d68138a2381afbdd0876c3cb2a22389043fa01c4badede1228ee073032b07a27", - strip_prefix = "cython-c2b80d87658a8525ce091cbe146cb7eaa29fed5c", - urls = [ - "https://github.com/cython/cython/archive/c2b80d87658a8525ce091cbe146cb7eaa29fed5c.tar.gz", - ], +# TODO(https://github.com/grpc/grpc/issues/18331): Move off of this dependency. +git_repository( + name = "org_pubref_rules_protobuf", + remote = "https://github.com/ghostwriternr/rules_protobuf", + tag = "v0.8.2.1-alpha", ) -load("//third_party/py:python_configure.bzl", "python_configure") - -python_configure(name = "local_config_python") - git_repository( name = "io_bazel_rules_python", commit = "8b5d0683a7d878b28fffe464779c8a53659fc645", @@ -39,24 +32,21 @@ git_repository( load("@io_bazel_rules_python//python:pip.bzl", "pip_repositories", "pip_import") -pip_repositories() - pip_import( name = "grpc_python_dependencies", requirements = "//:requirements.bazel.txt", ) -load("@grpc_python_dependencies//:requirements.bzl", "pip_install") - -pip_install() - -# NOTE(https://github.com/pubref/rules_protobuf/pull/196): Switch to upstream repo after this gets merged. -git_repository( - name = "org_pubref_rules_protobuf", - remote = "https://github.com/ghostwriternr/rules_protobuf", - tag = "v0.8.2.1-alpha", +http_archive( + name = "cython", + build_file = "//third_party:cython.BUILD", + sha256 = "d68138a2381afbdd0876c3cb2a22389043fa01c4badede1228ee073032b07a27", + strip_prefix = "cython-c2b80d87658a8525ce091cbe146cb7eaa29fed5c", + urls = [ + "https://github.com/cython/cython/archive/c2b80d87658a8525ce091cbe146cb7eaa29fed5c.tar.gz", + ], ) -load("@org_pubref_rules_protobuf//python:rules.bzl", "py_proto_repositories") +load("//bazel:grpc_python_deps.bzl", "grpc_python_deps") -py_proto_repositories() +grpc_python_deps() diff --git a/bazel/grpc_python_deps.bzl b/bazel/grpc_python_deps.bzl new file mode 100644 index 00000000000..ec3df19e03a --- /dev/null +++ b/bazel/grpc_python_deps.bzl @@ -0,0 +1,16 @@ +load("//third_party/py:python_configure.bzl", "python_configure") +load("@io_bazel_rules_python//python:pip.bzl", "pip_repositories") +load("@grpc_python_dependencies//:requirements.bzl", "pip_install") +load("@org_pubref_rules_protobuf//python:rules.bzl", "py_proto_repositories") + +def grpc_python_deps(): + # TODO(https://github.com/grpc/grpc/issues/18256): Remove conditional. + if hasattr(native, "http_archive"): + python_configure(name = "local_config_python") + pip_repositories() + pip_install() + py_proto_repositories() + else: + print("Building Python gRPC with bazel 23.0+ is disabled pending " + + "resolution of https://github.com/grpc/grpc/issues/18256.") + diff --git a/build.yaml b/build.yaml index d5ce77c2844..888b613dc0e 100644 --- a/build.yaml +++ b/build.yaml @@ -1352,6 +1352,7 @@ filegroups: - include/grpcpp/ext/health_check_service_server_builder_option.h - include/grpcpp/generic/async_generic_service.h - include/grpcpp/generic/generic_stub.h + - include/grpcpp/generic/generic_stub_impl.h - include/grpcpp/grpcpp.h - include/grpcpp/health_check_service_interface.h - include/grpcpp/health_check_service_interface_impl.h @@ -1377,6 +1378,7 @@ filegroups: - include/grpcpp/security/auth_metadata_processor_impl.h - include/grpcpp/security/credentials.h - include/grpcpp/security/server_credentials.h + - include/grpcpp/security/server_credentials_impl.h - include/grpcpp/server.h - include/grpcpp/server_builder.h - include/grpcpp/server_context.h @@ -1750,6 +1752,7 @@ libs: public_headers: - include/grpc++/ext/proto_server_reflection_plugin.h - include/grpcpp/ext/proto_server_reflection_plugin.h + - include/grpcpp/ext/proto_server_reflection_plugin_impl.h headers: - src/cpp/ext/proto_server_reflection.h src: diff --git a/doc/PROTOCOL-HTTP2.md b/doc/PROTOCOL-HTTP2.md index a354dad8636..e73e682bbe3 100644 --- a/doc/PROTOCOL-HTTP2.md +++ b/doc/PROTOCOL-HTTP2.md @@ -61,6 +61,8 @@ the form shown above. If **Timeout** is omitted a server should assume an infinite timeout. Client implementations are free to send a default minimum timeout based on their deployment requirements. +If **Content-Type** does not begin with "application/grpc", gRPC servers SHOULD respond with HTTP status of 415 (Unsupported Media Type). This will prevent other HTTP/2 clients from interpreting a gRPC error response, which uses status 200 (OK), as successful. + **Custom-Metadata** is an arbitrary set of key-value pairs defined by the application layer. Header names starting with "grpc-" but not listed here are reserved for future GRPC use and should not be used by applications as **Custom-Metadata**. Note that HTTP2 does not allow arbitrary octet sequences for header values so binary header values must be encoded using Base64 as per https://tools.ietf.org/html/rfc4648#section-4. Implementations MUST accept padded and un-padded values and should emit un-padded values. Applications define binary headers by having their names end with "-bin". Runtime libraries use this suffix to detect binary headers and properly apply base64 encoding & decoding as headers are sent and received. @@ -255,5 +257,3 @@ to be used. * **Service-Name** → ?( {_proto package name_} "." ) {_service name_} * **Message-Type** → {_fully qualified proto message name_} * **Content-Type** → "application/grpc+proto" - - diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 602c66b93d9..051397f1e67 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -91,6 +91,7 @@ Pod::Spec.new do |s| 'include/grpcpp/ext/health_check_service_server_builder_option.h', 'include/grpcpp/generic/async_generic_service.h', 'include/grpcpp/generic/generic_stub.h', + 'include/grpcpp/generic/generic_stub_impl.h', 'include/grpcpp/grpcpp.h', 'include/grpcpp/health_check_service_interface.h', 'include/grpcpp/health_check_service_interface_impl.h', @@ -116,6 +117,7 @@ Pod::Spec.new do |s| 'include/grpcpp/security/auth_metadata_processor_impl.h', 'include/grpcpp/security/credentials.h', 'include/grpcpp/security/server_credentials.h', + 'include/grpcpp/security/server_credentials_impl.h', 'include/grpcpp/server.h', 'include/grpcpp/server_builder.h', 'include/grpcpp/server_context.h', diff --git a/grpc.gemspec b/grpc.gemspec index c128d07eaf8..b9d2107ee48 100644 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -30,7 +30,7 @@ Gem::Specification.new do |s| s.platform = Gem::Platform::RUBY s.add_dependency 'google-protobuf', '~> 3.7' - s.add_dependency 'googleapis-common-protos-types', '~> 1.0.0' + s.add_dependency 'googleapis-common-protos-types', '~> 1.0' s.add_development_dependency 'bundler', '~> 1.9' s.add_development_dependency 'facter', '~> 2.4' diff --git a/include/grpcpp/ext/proto_server_reflection_plugin.h b/include/grpcpp/ext/proto_server_reflection_plugin.h index 584e44190a0..f6f2202ffb3 100644 --- a/include/grpcpp/ext/proto_server_reflection_plugin.h +++ b/include/grpcpp/ext/proto_server_reflection_plugin.h @@ -1,6 +1,6 @@ /* * - * Copyright 2015 gRPC authors. + * 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. @@ -19,37 +19,17 @@ #ifndef GRPCPP_EXT_PROTO_SERVER_REFLECTION_PLUGIN_H #define GRPCPP_EXT_PROTO_SERVER_REFLECTION_PLUGIN_H -#include -#include - -namespace grpc_impl { - -class ServerInitializer; -} -namespace grpc { -class ProtoServerReflection; -} // namespace grpc +#include namespace grpc { namespace reflection { -class ProtoServerReflectionPlugin : public ::grpc::ServerBuilderPlugin { - public: - ProtoServerReflectionPlugin(); - ::grpc::string name() override; - void InitServer(::grpc_impl::ServerInitializer* si) override; - void Finish(::grpc_impl::ServerInitializer* si) override; - void ChangeArguments(const ::grpc::string& name, void* value) override; - bool has_async_methods() const override; - bool has_sync_methods() const override; - - private: - std::shared_ptr reflection_service_; -}; +typedef ::grpc_impl::reflection::ProtoServerReflectionPlugin + ProtoServerReflectionPlugin; -/// Add proto reflection plugin to \a ServerBuilder. -/// This function should be called at the static initialization time. -void InitProtoReflectionServerBuilderPlugin(); +static inline void InitProtoReflectionServerBuilderPlugin() { + ::grpc_impl::reflection::InitProtoReflectionServerBuilderPlugin(); +} } // namespace reflection } // namespace grpc diff --git a/include/grpcpp/ext/proto_server_reflection_plugin_impl.h b/include/grpcpp/ext/proto_server_reflection_plugin_impl.h new file mode 100644 index 00000000000..a06fe14cdd7 --- /dev/null +++ b/include/grpcpp/ext/proto_server_reflection_plugin_impl.h @@ -0,0 +1,55 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_EXT_PROTO_SERVER_REFLECTION_PLUGIN_IMPL_H +#define GRPCPP_EXT_PROTO_SERVER_REFLECTION_PLUGIN_IMPL_H + +#include +#include + +namespace grpc { +class ProtoServerReflection; +} // namespace grpc + +namespace grpc_impl { +class ServerInitializer; + +namespace reflection { + +class ProtoServerReflectionPlugin : public ::grpc::ServerBuilderPlugin { + public: + ProtoServerReflectionPlugin(); + ::grpc::string name() override; + void InitServer(::grpc_impl::ServerInitializer* si) override; + void Finish(::grpc_impl::ServerInitializer* si) override; + void ChangeArguments(const ::grpc::string& name, void* value) override; + bool has_async_methods() const override; + bool has_sync_methods() const override; + + private: + std::shared_ptr reflection_service_; +}; + +/// Add proto reflection plugin to \a ServerBuilder. +/// This function should be called at the static initialization time. +void InitProtoReflectionServerBuilderPlugin(); + +} // namespace reflection +} // namespace grpc_impl + +#endif // GRPCPP_EXT_PROTO_SERVER_REFLECTION_PLUGIN_IMPL_H diff --git a/include/grpcpp/generic/generic_stub.h b/include/grpcpp/generic/generic_stub.h index 9252599bac3..f4c4664f53c 100644 --- a/include/grpcpp/generic/generic_stub.h +++ b/include/grpcpp/generic/generic_stub.h @@ -19,85 +19,11 @@ #ifndef GRPCPP_GENERIC_GENERIC_STUB_H #define GRPCPP_GENERIC_GENERIC_STUB_H -#include - -#include -#include -#include -#include -#include +#include namespace grpc { -class CompletionQueue; -typedef ClientAsyncReaderWriter - GenericClientAsyncReaderWriter; -typedef ClientAsyncResponseReader GenericClientAsyncResponseReader; - -/// Generic stubs provide a type-unsafe interface to call gRPC methods -/// by name. -class GenericStub final { - public: - explicit GenericStub(std::shared_ptr channel) - : channel_(channel) {} - - /// Setup a call to a named method \a method using \a context, but don't - /// start it. Let it be started explicitly with StartCall and a tag. - /// The return value only indicates whether or not registration of the call - /// succeeded (i.e. the call won't proceed if the return value is nullptr). - std::unique_ptr PrepareCall( - ClientContext* context, const grpc::string& method, CompletionQueue* cq); - - /// Setup a unary call to a named method \a method using \a context, and don't - /// start it. Let it be started explicitly with StartCall. - /// The return value only indicates whether or not registration of the call - /// succeeded (i.e. the call won't proceed if the return value is nullptr). - std::unique_ptr PrepareUnaryCall( - ClientContext* context, const grpc::string& method, - const ByteBuffer& request, CompletionQueue* cq); - - /// DEPRECATED for multi-threaded use - /// Begin a call to a named method \a method using \a context. - /// A tag \a tag will be delivered to \a cq when the call has been started - /// (i.e, initial metadata has been sent). - /// The return value only indicates whether or not registration of the call - /// succeeded (i.e. the call won't proceed if the return value is nullptr). - std::unique_ptr Call( - ClientContext* context, const grpc::string& method, CompletionQueue* cq, - void* tag); - - /// NOTE: class experimental_type is not part of the public API of this class - /// TODO(vjpai): Move these contents to the public API of GenericStub when - /// they are no longer experimental - class experimental_type { - public: - explicit experimental_type(GenericStub* stub) : stub_(stub) {} - - /// Setup and start a unary call to a named method \a method using - /// \a context and specifying the \a request and \a response buffers. - void UnaryCall(ClientContext* context, const grpc::string& method, - const ByteBuffer* request, ByteBuffer* response, - std::function on_completion); - - /// Setup a call to a named method \a method using \a context and tied to - /// \a reactor . Like any other bidi streaming RPC, it will not be activated - /// until StartCall is invoked on its reactor. - void PrepareBidiStreamingCall( - ClientContext* context, const grpc::string& method, - experimental::ClientBidiReactor* reactor); - - private: - GenericStub* stub_; - }; - - /// NOTE: The function experimental() is not stable public API. It is a view - /// to the experimental components of this class. It may be changed or removed - /// at any time. - experimental_type experimental() { return experimental_type(this); } - - private: - std::shared_ptr channel_; -}; +typedef ::grpc_impl::GenericStub GenericStub; } // namespace grpc diff --git a/include/grpcpp/generic/generic_stub_impl.h b/include/grpcpp/generic/generic_stub_impl.h new file mode 100644 index 00000000000..2d6a11de923 --- /dev/null +++ b/include/grpcpp/generic/generic_stub_impl.h @@ -0,0 +1,108 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_GENERIC_GENERIC_STUB_IMPL_H +#define GRPCPP_GENERIC_GENERIC_STUB_IMPL_H + +#include + +#include +#include +#include +#include +#include + +namespace grpc { + +class CompletionQueue; +typedef ClientAsyncReaderWriter + GenericClientAsyncReaderWriter; +typedef ClientAsyncResponseReader GenericClientAsyncResponseReader; +} // namespace grpc +namespace grpc_impl { + +/// Generic stubs provide a type-unsafe interface to call gRPC methods +/// by name. +class GenericStub final { + public: + explicit GenericStub(std::shared_ptr channel) + : channel_(channel) {} + + /// Setup a call to a named method \a method using \a context, but don't + /// start it. Let it be started explicitly with StartCall and a tag. + /// The return value only indicates whether or not registration of the call + /// succeeded (i.e. the call won't proceed if the return value is nullptr). + std::unique_ptr PrepareCall( + grpc::ClientContext* context, const grpc::string& method, + grpc::CompletionQueue* cq); + + /// Setup a unary call to a named method \a method using \a context, and don't + /// start it. Let it be started explicitly with StartCall. + /// The return value only indicates whether or not registration of the call + /// succeeded (i.e. the call won't proceed if the return value is nullptr). + std::unique_ptr PrepareUnaryCall( + grpc::ClientContext* context, const grpc::string& method, + const grpc::ByteBuffer& request, grpc::CompletionQueue* cq); + + /// DEPRECATED for multi-threaded use + /// Begin a call to a named method \a method using \a context. + /// A tag \a tag will be delivered to \a cq when the call has been started + /// (i.e, initial metadata has been sent). + /// The return value only indicates whether or not registration of the call + /// succeeded (i.e. the call won't proceed if the return value is nullptr). + std::unique_ptr Call( + grpc::ClientContext* context, const grpc::string& method, + grpc::CompletionQueue* cq, void* tag); + + /// NOTE: class experimental_type is not part of the public API of this class + /// TODO(vjpai): Move these contents to the public API of GenericStub when + /// they are no longer experimental + class experimental_type { + public: + explicit experimental_type(GenericStub* stub) : stub_(stub) {} + + /// Setup and start a unary call to a named method \a method using + /// \a context and specifying the \a request and \a response buffers. + void UnaryCall(grpc::ClientContext* context, const grpc::string& method, + const grpc::ByteBuffer* request, grpc::ByteBuffer* response, + std::function on_completion); + + /// Setup a call to a named method \a method using \a context and tied to + /// \a reactor . Like any other bidi streaming RPC, it will not be activated + /// until StartCall is invoked on its reactor. + void PrepareBidiStreamingCall( + grpc::ClientContext* context, const grpc::string& method, + grpc::experimental::ClientBidiReactor* reactor); + + private: + GenericStub* stub_; + }; + + /// NOTE: The function experimental() is not stable public API. It is a view + /// to the experimental components of this class. It may be changed or removed + /// at any time. + experimental_type experimental() { return experimental_type(this); } + + private: + std::shared_ptr channel_; +}; + +} // namespace grpc_impl + +#endif // GRPCPP_GENERIC_GENERIC_STUB_IMPL_H diff --git a/include/grpcpp/impl/codegen/server_interface.h b/include/grpcpp/impl/codegen/server_interface.h index f599e037fd5..a0b0a580979 100644 --- a/include/grpcpp/impl/codegen/server_interface.h +++ b/include/grpcpp/impl/codegen/server_interface.h @@ -28,6 +28,10 @@ #include #include +namespace grpc_impl { + +class ServerCredentials; +} namespace grpc { class AsyncGenericService; @@ -35,7 +39,6 @@ class Channel; class GenericServerContext; class ServerCompletionQueue; class ServerContext; -class ServerCredentials; class Service; extern CoreCodegenInterface* g_core_codegen_interface; @@ -150,7 +153,7 @@ class ServerInterface : public internal::CallHook { /// /// \warning It's an error to call this method on an already started server. virtual int AddListeningPort(const grpc::string& addr, - ServerCredentials* creds) = 0; + grpc_impl::ServerCredentials* creds) = 0; /// Start the server. /// diff --git a/include/grpcpp/security/server_credentials.h b/include/grpcpp/security/server_credentials.h index 25b25c9639b..57f733886f4 100644 --- a/include/grpcpp/security/server_credentials.h +++ b/include/grpcpp/security/server_credentials.h @@ -1,6 +1,6 @@ /* * - * Copyright 2015 gRPC authors. + * 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. @@ -19,14 +19,7 @@ #ifndef GRPCPP_SECURITY_SERVER_CREDENTIALS_H #define GRPCPP_SECURITY_SERVER_CREDENTIALS_H -#include -#include - -#include -#include -#include - -struct grpc_server; +#include namespace grpc_impl { @@ -34,27 +27,7 @@ class Server; } // namespace grpc_impl namespace grpc { -/// Wrapper around \a grpc_server_credentials, a way to authenticate a server. -class ServerCredentials { - public: - virtual ~ServerCredentials(); - - /// This method is not thread-safe and has to be called before the server is - /// started. The last call to this function wins. - virtual void SetAuthMetadataProcessor( - const std::shared_ptr& processor) = 0; - - private: - friend class ::grpc_impl::Server; - - /// Tries to bind \a server to the given \a addr (eg, localhost:1234, - /// 192.168.1.1:31416, [::1]:27182, etc.) - /// - /// \return bound port number on sucess, 0 on failure. - // TODO(dgq): the "port" part seems to be a misnomer. - virtual int AddPortToServer(const grpc::string& addr, - grpc_server* server) = 0; -}; +typedef ::grpc_impl::ServerCredentials ServerCredentials; /// Options to create ServerCredentials with SSL struct SslServerCredentialsOptions { @@ -82,27 +55,29 @@ struct SslServerCredentialsOptions { grpc_ssl_client_certificate_request_type client_certificate_request; }; -/// Builds SSL ServerCredentials given SSL specific options -std::shared_ptr SslServerCredentials( - const SslServerCredentialsOptions& options); +static inline std::shared_ptr SslServerCredentials( + const SslServerCredentialsOptions& options) { + return ::grpc_impl::SslServerCredentials(options); +} -/// Builds insecure server credentials. -std::shared_ptr InsecureServerCredentials(); +static inline std::shared_ptr InsecureServerCredentials() { + return ::grpc_impl::InsecureServerCredentials(); +} namespace experimental { -/// Options to create ServerCredentials with ALTS -struct AltsServerCredentialsOptions { - /// Add fields if needed. -}; +typedef ::grpc_impl::experimental::AltsServerCredentialsOptions + AltsServerCredentialsOptions; -/// Builds ALTS ServerCredentials given ALTS specific options -std::shared_ptr AltsServerCredentials( - const AltsServerCredentialsOptions& options); +static inline std::shared_ptr AltsServerCredentials( + const AltsServerCredentialsOptions& options) { + return ::grpc_impl::experimental::AltsServerCredentials(options); +} -/// Builds Local ServerCredentials. -std::shared_ptr LocalServerCredentials( - grpc_local_connect_type type); +static inline std::shared_ptr LocalServerCredentials( + grpc_local_connect_type type) { + return ::grpc_impl::experimental::LocalServerCredentials(type); +} } // namespace experimental } // namespace grpc diff --git a/include/grpcpp/security/server_credentials_impl.h b/include/grpcpp/security/server_credentials_impl.h new file mode 100644 index 00000000000..0439548d14a --- /dev/null +++ b/include/grpcpp/security/server_credentials_impl.h @@ -0,0 +1,85 @@ +/* + * + * Copyright 2015 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_SECURITY_SERVER_CREDENTIALS_IMPL_H +#define GRPCPP_SECURITY_SERVER_CREDENTIALS_IMPL_H + +#include +#include + +#include +#include +#include + +struct grpc_server; + +namespace grpc { + +struct SslServerCredentialsOptions; +} // namespace grpc +namespace grpc_impl { +class Server; + +/// Wrapper around \a grpc_server_credentials, a way to authenticate a server. +class ServerCredentials { + public: + virtual ~ServerCredentials(); + + /// This method is not thread-safe and has to be called before the server is + /// started. The last call to this function wins. + virtual void SetAuthMetadataProcessor( + const std::shared_ptr& processor) = 0; + + private: + friend class ::grpc_impl::Server; + + /// Tries to bind \a server to the given \a addr (eg, localhost:1234, + /// 192.168.1.1:31416, [::1]:27182, etc.) + /// + /// \return bound port number on sucess, 0 on failure. + // TODO(dgq): the "port" part seems to be a misnomer. + virtual int AddPortToServer(const grpc::string& addr, + grpc_server* server) = 0; +}; + +/// Builds SSL ServerCredentials given SSL specific options +std::shared_ptr SslServerCredentials( + const grpc::SslServerCredentialsOptions& options); + +/// Builds insecure server credentials. +std::shared_ptr InsecureServerCredentials(); + +namespace experimental { + +/// Options to create ServerCredentials with ALTS +struct AltsServerCredentialsOptions { + /// Add fields if needed. +}; + +/// Builds ALTS ServerCredentials given ALTS specific options +std::shared_ptr AltsServerCredentials( + const AltsServerCredentialsOptions& options); + +/// Builds Local ServerCredentials. +std::shared_ptr LocalServerCredentials( + grpc_local_connect_type type); + +} // namespace experimental +} // namespace grpc_impl + +#endif // GRPCPP_SECURITY_SERVER_CREDENTIALS_IMPL_H diff --git a/include/grpcpp/server_builder.h b/include/grpcpp/server_builder.h index 0976b09bb8c..0880922f39f 100644 --- a/include/grpcpp/server_builder.h +++ b/include/grpcpp/server_builder.h @@ -38,14 +38,15 @@ struct grpc_resource_quota; namespace grpc_impl { class Server; +class ServerCredentials; class ResourceQuota; } // namespace grpc_impl + namespace grpc { class AsyncGenericService; class CompletionQueue; class ServerCompletionQueue; -class ServerCredentials; class Service; namespace testing { @@ -96,9 +97,10 @@ class ServerBuilder { /// number bound to the \a grpc::Server for the corresponding endpoint after /// it is successfully bound by BuildAndStart(), 0 otherwise. AddListeningPort /// does not modify this pointer. - ServerBuilder& AddListeningPort(const grpc::string& addr_uri, - std::shared_ptr creds, - int* selected_port = nullptr); + ServerBuilder& AddListeningPort( + const grpc::string& addr_uri, + std::shared_ptr creds, + int* selected_port = nullptr); /// Add a completion queue for handling asynchronous services. /// @@ -255,7 +257,7 @@ class ServerBuilder { /// Experimental, to be deprecated struct Port { grpc::string addr; - std::shared_ptr creds; + std::shared_ptr creds; int* selected_port; }; @@ -323,7 +325,7 @@ class ServerBuilder { /// List of completion queues added via \a AddCompletionQueue method. std::vector cqs_; - std::shared_ptr creds_; + std::shared_ptr creds_; std::vector> plugins_; grpc_resource_quota* resource_quota_; AsyncGenericService* generic_service_{nullptr}; diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index 34a24e2c712..86938a51d9b 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -149,45 +149,48 @@ struct QueuedPick { }; struct client_channel_channel_data { + // + // Fields set at construction and never modified. + // bool deadline_checking_enabled; bool enable_retries; size_t per_rpc_retry_buffer_size; - - /** combiner protecting all variables below in this data structure */ - grpc_combiner* combiner; - /** owning stack */ grpc_channel_stack* owning_stack; - /** interested parties (owned) */ - grpc_pollset_set* interested_parties; - // Client channel factory. grpc_core::ClientChannelFactory* client_channel_factory; - // Subchannel pool. - grpc_core::RefCountedPtr subchannel_pool; grpc_core::channelz::ClientChannelNode* channelz_node; - // Resolving LB policy. - grpc_core::OrphanablePtr resolving_lb_policy; - // Subchannel picker from LB policy. + // + // Fields used in the data plane. Protected by data_plane_combiner. + // + grpc_combiner* data_plane_combiner; grpc_core::UniquePtr picker; - // Linked list of queued picks. - QueuedPick* queued_picks; - - bool have_service_config; - /** retry throttle data from service config */ + QueuedPick* queued_picks; // Linked list of queued picks. + // Data from service config. + bool received_service_config_data; grpc_core::RefCountedPtr retry_throttle_data; - /** per-method service config data */ grpc_core::RefCountedPtr method_params_table; - /* the following properties are guarded by a mutex since APIs require them - to be instantaneously available */ + // + // Fields used in the control plane. Protected by combiner. + // + grpc_combiner* combiner; + grpc_pollset_set* interested_parties; + grpc_core::RefCountedPtr subchannel_pool; + grpc_core::OrphanablePtr resolving_lb_policy; + grpc_connectivity_state_tracker state_tracker; + + // + // Fields accessed from both data plane and control plane combiners. + // + grpc_core::Atomic disconnect_error; + + // The following properties are guarded by a mutex since APIs require them + // to be instantaneously available. gpr_mu info_mu; grpc_core::UniquePtr info_lb_policy_name; grpc_core::UniquePtr info_service_config_json; - grpc_connectivity_state_tracker state_tracker; - grpc_error* disconnect_error; - grpc_core::ManualConstructor< grpc_core::ExternalConnectivityWatcher::WatcherList> external_connectivity_watcher_list; @@ -214,30 +217,98 @@ static const char* get_channel_connectivity_state_change_string( GPR_UNREACHABLE_CODE(return "UNKNOWN"); } -static void set_connectivity_state_and_picker_locked( - channel_data* chand, grpc_connectivity_state state, grpc_error* state_error, - const char* reason, - grpc_core::UniquePtr picker) { - // Update connectivity state. - grpc_connectivity_state_set(&chand->state_tracker, state, state_error, - reason); - if (chand->channelz_node != nullptr) { - chand->channelz_node->AddTraceEvent( - grpc_core::channelz::ChannelTrace::Severity::Info, - grpc_slice_from_static_string( - get_channel_connectivity_state_change_string(state))); +namespace grpc_core { +namespace { + +// A fire-and-forget class that sets the channel's connectivity state +// and then hops into the data plane combiner to update the picker. +// Must be instantiated while holding the control plane combiner. +// Deletes itself when done. +class ConnectivityStateAndPickerSetter { + public: + ConnectivityStateAndPickerSetter( + channel_data* chand, grpc_connectivity_state state, + grpc_error* state_error, const char* reason, + UniquePtr picker) + : chand_(chand), picker_(std::move(picker)) { + // Update connectivity state here, while holding control plane combiner. + grpc_connectivity_state_set(&chand->state_tracker, state, state_error, + reason); + if (chand->channelz_node != nullptr) { + chand->channelz_node->AddTraceEvent( + channelz::ChannelTrace::Severity::Info, + grpc_slice_from_static_string( + get_channel_connectivity_state_change_string(state))); + } + // Bounce into the data plane combiner to reset the picker. + GRPC_CHANNEL_STACK_REF(chand->owning_stack, + "ConnectivityStateAndPickerSetter"); + GRPC_CLOSURE_INIT(&closure_, SetPicker, this, + grpc_combiner_scheduler(chand->data_plane_combiner)); + GRPC_CLOSURE_SCHED(&closure_, GRPC_ERROR_NONE); } - // Update picker. - chand->picker = std::move(picker); - // Re-process queued picks. - for (QueuedPick* pick = chand->queued_picks; pick != nullptr; - pick = pick->next) { - start_pick_locked(pick->elem, GRPC_ERROR_NONE); + + private: + static void SetPicker(void* arg, grpc_error* ignored) { + auto* self = static_cast(arg); + // Update picker. + self->chand_->picker = std::move(self->picker_); + // Re-process queued picks. + for (QueuedPick* pick = self->chand_->queued_picks; pick != nullptr; + pick = pick->next) { + start_pick_locked(pick->elem, GRPC_ERROR_NONE); + } + // Clean up. + GRPC_CHANNEL_STACK_UNREF(self->chand_->owning_stack, + "ConnectivityStateAndPickerSetter"); + Delete(self); } -} -namespace grpc_core { -namespace { + channel_data* chand_; + UniquePtr picker_; + grpc_closure closure_; +}; + +// A fire-and-forget class that sets the channel's service config data +// in the data plane combiner. Deletes itself when done. +class ServiceConfigSetter { + public: + ServiceConfigSetter( + channel_data* chand, + RefCountedPtr retry_throttle_data, + RefCountedPtr method_params_table) + : chand_(chand), + retry_throttle_data_(std::move(retry_throttle_data)), + method_params_table_(std::move(method_params_table)) { + GRPC_CHANNEL_STACK_REF(chand->owning_stack, "ServiceConfigSetter"); + GRPC_CLOSURE_INIT(&closure_, SetServiceConfigData, this, + grpc_combiner_scheduler(chand->data_plane_combiner)); + GRPC_CLOSURE_SCHED(&closure_, GRPC_ERROR_NONE); + } + + private: + static void SetServiceConfigData(void* arg, grpc_error* ignored) { + ServiceConfigSetter* self = static_cast(arg); + channel_data* chand = self->chand_; + // Update channel state. + chand->received_service_config_data = true; + chand->retry_throttle_data = std::move(self->retry_throttle_data_); + chand->method_params_table = std::move(self->method_params_table_); + // Apply service config to queued picks. + for (QueuedPick* pick = chand->queued_picks; pick != nullptr; + pick = pick->next) { + maybe_apply_service_config_to_call_locked(pick->elem); + } + // Clean up. + GRPC_CHANNEL_STACK_UNREF(self->chand_->owning_stack, "ServiceConfigSetter"); + Delete(self); + } + + channel_data* chand_; + RefCountedPtr retry_throttle_data_; + RefCountedPtr method_params_table_; + grpc_closure closure_; +}; // // ExternalConnectivityWatcher::WatcherList @@ -387,8 +458,10 @@ class ClientChannelControlHelper void UpdateState( grpc_connectivity_state state, grpc_error* state_error, UniquePtr picker) override { + grpc_error* disconnect_error = + chand_->disconnect_error.Load(grpc_core::MemoryOrder::ACQUIRE); if (grpc_client_channel_routing_trace.enabled()) { - const char* extra = chand_->disconnect_error == GRPC_ERROR_NONE + const char* extra = disconnect_error == GRPC_ERROR_NONE ? "" : " (ignoring -- channel shutting down)"; gpr_log(GPR_INFO, "chand=%p: update: state=%s error=%s picker=%p%s", @@ -396,9 +469,10 @@ class ClientChannelControlHelper grpc_error_string(state_error), picker.get(), extra); } // Do update only if not shutting down. - if (chand_->disconnect_error == GRPC_ERROR_NONE) { - set_connectivity_state_and_picker_locked(chand_, state, state_error, - "helper", std::move(picker)); + if (disconnect_error == GRPC_ERROR_NONE) { + // Will delete itself. + New(chand_, state, state_error, + "helper", std::move(picker)); } else { GRPC_ERROR_UNREF(state_error); } @@ -420,7 +494,6 @@ static bool process_resolver_result_locked( void* arg, grpc_core::Resolver::Result* result, const char** lb_policy_name, grpc_core::RefCountedPtr* lb_policy_config) { channel_data* chand = static_cast(arg); - chand->have_service_config = true; ProcessedResolverResult resolver_result(result, chand->enable_retries); grpc_core::UniquePtr service_config_json = resolver_result.service_config_json(); @@ -428,9 +501,11 @@ static bool process_resolver_result_locked( gpr_log(GPR_INFO, "chand=%p: resolver returned service config: \"%s\"", chand, service_config_json.get()); } - // Update channel state. - chand->retry_throttle_data = resolver_result.retry_throttle_data(); - chand->method_params_table = resolver_result.method_params_table(); + // Create service config setter to update channel state in the data + // plane combiner. Destroys itself when done. + grpc_core::New( + chand, resolver_result.retry_throttle_data(), + resolver_result.method_params_table()); // Swap out the data used by cc_get_channel_info(). gpr_mu_lock(&chand->info_mu); chand->info_lb_policy_name = resolver_result.lb_policy_name(); @@ -445,11 +520,6 @@ static bool process_resolver_result_locked( // Return results. *lb_policy_name = chand->info_lb_policy_name.get(); *lb_policy_config = resolver_result.lb_policy_config(); - // Apply service config to queued picks. - for (QueuedPick* pick = chand->queued_picks; pick != nullptr; - pick = pick->next) { - maybe_apply_service_config_to_call_locked(pick->elem); - } return service_config_changed; } @@ -507,12 +577,16 @@ static void start_transport_op_locked(void* arg, grpc_error* error_ignored) { } if (op->disconnect_with_error != GRPC_ERROR_NONE) { - chand->disconnect_error = op->disconnect_with_error; + grpc_error* error = GRPC_ERROR_NONE; + GPR_ASSERT(chand->disconnect_error.CompareExchangeStrong( + &error, op->disconnect_with_error, grpc_core::MemoryOrder::ACQ_REL, + grpc_core::MemoryOrder::ACQUIRE)); grpc_pollset_set_del_pollset_set( chand->resolving_lb_policy->interested_parties(), chand->interested_parties); chand->resolving_lb_policy.reset(); - set_connectivity_state_and_picker_locked( + // Will delete itself. + grpc_core::New( chand, GRPC_CHANNEL_SHUTDOWN, GRPC_ERROR_REF(op->disconnect_with_error), "shutdown from API", grpc_core::UniquePtr( @@ -562,10 +636,12 @@ static grpc_error* cc_init_channel_elem(grpc_channel_element* elem, GPR_ASSERT(args->is_last); GPR_ASSERT(elem->filter == &grpc_client_channel_filter); // Initialize data members. + chand->data_plane_combiner = grpc_combiner_create(); chand->combiner = grpc_combiner_create(); grpc_connectivity_state_init(&chand->state_tracker, GRPC_CHANNEL_IDLE, "client_channel"); - chand->disconnect_error = GRPC_ERROR_NONE; + chand->disconnect_error.Store(GRPC_ERROR_NONE, + grpc_core::MemoryOrder::RELAXED); gpr_mu_init(&chand->info_mu); chand->external_connectivity_watcher_list.Init(); chand->owning_stack = args->channel_stack; @@ -671,8 +747,10 @@ static void cc_destroy_channel_elem(grpc_channel_element* elem) { chand->method_params_table.reset(); grpc_client_channel_stop_backup_polling(chand->interested_parties); grpc_pollset_set_destroy(chand->interested_parties); + GRPC_COMBINER_UNREF(chand->data_plane_combiner, "client_channel"); GRPC_COMBINER_UNREF(chand->combiner, "client_channel"); - GRPC_ERROR_UNREF(chand->disconnect_error); + GRPC_ERROR_UNREF( + chand->disconnect_error.Load(grpc_core::MemoryOrder::RELAXED)); grpc_connectivity_state_destroy(&chand->state_tracker); gpr_mu_destroy(&chand->info_mu); chand->external_connectivity_watcher_list.Destroy(); @@ -1421,7 +1499,7 @@ static void do_retry(grpc_call_element* elem, } // Schedule retry after computed delay. GRPC_CLOSURE_INIT(&calld->pick_closure, start_pick_locked, elem, - grpc_combiner_scheduler(chand->combiner)); + grpc_combiner_scheduler(chand->data_plane_combiner)); grpc_timer_init(&calld->retry_timer, next_attempt_time, &calld->pick_closure); // Update bookkeeping. if (retry_state != nullptr) retry_state->retry_dispatched = true; @@ -2648,7 +2726,7 @@ class QueuedPickCanceller { auto* chand = static_cast(elem->channel_data); GRPC_CALL_STACK_REF(calld->owning_call, "QueuedPickCanceller"); GRPC_CLOSURE_INIT(&closure_, &CancelLocked, this, - grpc_combiner_scheduler(chand->combiner)); + grpc_combiner_scheduler(chand->data_plane_combiner)); grpc_call_combiner_set_notify_on_cancel(calld->call_combiner, &closure_); } @@ -2788,7 +2866,7 @@ static void maybe_apply_service_config_to_call_locked(grpc_call_element* elem) { call_data* calld = static_cast(elem->call_data); // Apply service config data to the call only once, and only if the // channel has the data available. - if (GPR_LIKELY(chand->have_service_config && + if (GPR_LIKELY(chand->received_service_config_data && !calld->service_config_applied)) { calld->service_config_applied = true; apply_service_config_to_call_locked(elem); @@ -2836,7 +2914,7 @@ static void start_pick_locked(void* arg, grpc_error* error) { .send_initial_metadata_flags; // Apply service config to call if needed. maybe_apply_service_config_to_call_locked(elem); - // When done, we schedule this closure to leave the channel combiner. + // When done, we schedule this closure to leave the data plane combiner. GRPC_CLOSURE_INIT(&calld->pick_closure, pick_done, elem, grpc_schedule_on_exec_ctx); // Attempt pick. @@ -2851,12 +2929,14 @@ static void start_pick_locked(void* arg, grpc_error* error) { grpc_error_string(error)); } switch (pick_result) { - case LoadBalancingPolicy::PICK_TRANSIENT_FAILURE: + case LoadBalancingPolicy::PICK_TRANSIENT_FAILURE: { // If we're shutting down, fail all RPCs. - if (chand->disconnect_error != GRPC_ERROR_NONE) { + grpc_error* disconnect_error = + chand->disconnect_error.Load(grpc_core::MemoryOrder::ACQUIRE); + if (disconnect_error != GRPC_ERROR_NONE) { GRPC_ERROR_UNREF(error); GRPC_CLOSURE_SCHED(&calld->pick_closure, - GRPC_ERROR_REF(chand->disconnect_error)); + GRPC_ERROR_REF(disconnect_error)); break; } // If wait_for_ready is false, then the error indicates the RPC @@ -2882,7 +2962,8 @@ static void start_pick_locked(void* arg, grpc_error* error) { // If wait_for_ready is true, then queue to retry when we get a new // picker. GRPC_ERROR_UNREF(error); - // Fallthrough + } + // Fallthrough case LoadBalancingPolicy::PICK_QUEUE: if (!calld->pick_queued) add_call_to_queued_picks_locked(elem); break; @@ -2976,7 +3057,8 @@ static void cc_start_transport_stream_op_batch( } GRPC_CLOSURE_SCHED( GRPC_CLOSURE_INIT(&batch->handler_private.closure, start_pick_locked, - elem, grpc_combiner_scheduler(chand->combiner)), + elem, + grpc_combiner_scheduler(chand->data_plane_combiner)), GRPC_ERROR_NONE); } else { // For all other batches, release the call combiner. diff --git a/src/core/ext/filters/client_channel/health/health_check_client.cc b/src/core/ext/filters/client_channel/health/health_check_client.cc index 84a7f35ed30..a22d6450cbd 100644 --- a/src/core/ext/filters/client_channel/health/health_check_client.cc +++ b/src/core/ext/filters/client_channel/health/health_check_client.cc @@ -287,7 +287,6 @@ HealthCheckClient::CallState::CallState( ->GetInitialCallSizeEstimate(0))), payload_(context_) { grpc_call_combiner_init(&call_combiner_); - gpr_atm_rel_store(&seen_response_, static_cast(0)); } HealthCheckClient::CallState::~CallState() { @@ -295,9 +294,6 @@ HealthCheckClient::CallState::~CallState() { gpr_log(GPR_INFO, "HealthCheckClient %p: destroying CallState %p", health_check_client_.get(), this); } - // The subchannel call is in the arena, so reset the pointer before we destroy - // the arena. - call_.reset(); for (size_t i = 0; i < GRPC_CONTEXT_COUNT; i++) { if (context_[i].destroy != nullptr) { context_[i].destroy(context_[i].value); @@ -436,12 +432,22 @@ void HealthCheckClient::CallState::StartBatch( GRPC_ERROR_NONE, "start_subchannel_batch"); } +void HealthCheckClient::CallState::AfterCallStackDestruction( + void* arg, grpc_error* error) { + HealthCheckClient::CallState* self = + static_cast(arg); + self->Unref(DEBUG_LOCATION, "cancel"); +} + void HealthCheckClient::CallState::OnCancelComplete(void* arg, grpc_error* error) { HealthCheckClient::CallState* self = static_cast(arg); GRPC_CALL_COMBINER_STOP(&self->call_combiner_, "health_cancel"); - self->Unref(DEBUG_LOCATION, "cancel"); + GRPC_CLOSURE_INIT(&self->after_call_stack_destruction_, + AfterCallStackDestruction, self, grpc_schedule_on_exec_ctx); + self->call_->SetAfterCallStackDestroy(&self->after_call_stack_destruction_); + self->call_.reset(); } void HealthCheckClient::CallState::StartCancel(void* arg, grpc_error* error) { @@ -455,7 +461,9 @@ void HealthCheckClient::CallState::StartCancel(void* arg, grpc_error* error) { } void HealthCheckClient::CallState::Cancel() { - if (call_ != nullptr) { + bool expected = false; + if (cancelled_.CompareExchangeStrong(&expected, true, MemoryOrder::ACQ_REL, + MemoryOrder::ACQUIRE)) { Ref(DEBUG_LOCATION, "cancel").release(); GRPC_CALL_COMBINER_START( &call_combiner_, @@ -498,7 +506,7 @@ void HealthCheckClient::CallState::DoneReadingRecvMessage(grpc_error* error) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("backend unhealthy"); } health_check_client_->SetHealthStatus(state, error); - gpr_atm_rel_store(&seen_response_, static_cast(1)); + seen_response_.Store(true, MemoryOrder::RELEASE); grpc_slice_buffer_destroy_internal(&recv_message_buffer_); // Start another recv_message batch. // This re-uses the ref we're holding. @@ -631,7 +639,7 @@ void HealthCheckClient::CallState::CallEnded(bool retry) { health_check_client_->call_state_.reset(); if (retry) { GPR_ASSERT(!health_check_client_->shutting_down_); - if (static_cast(gpr_atm_acq_load(&seen_response_))) { + if (seen_response_.Load(MemoryOrder::ACQUIRE)) { // If the call fails after we've gotten a successful response, reset // the backoff and restart the call immediately. health_check_client_->retry_backoff_.Reset(); diff --git a/src/core/ext/filters/client_channel/health/health_check_client.h b/src/core/ext/filters/client_channel/health/health_check_client.h index 7af88a54cfc..1fa4487c403 100644 --- a/src/core/ext/filters/client_channel/health/health_check_client.h +++ b/src/core/ext/filters/client_channel/health/health_check_client.h @@ -22,13 +22,13 @@ #include #include -#include #include #include "src/core/ext/filters/client_channel/client_channel_channelz.h" #include "src/core/ext/filters/client_channel/subchannel.h" #include "src/core/lib/backoff/backoff.h" #include "src/core/lib/gpr/arena.h" +#include "src/core/lib/gprpp/atomic.h" #include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/call_combiner.h" @@ -91,6 +91,8 @@ class HealthCheckClient : public InternallyRefCounted { grpc_error* PullSliceFromRecvMessage(); void DoneReadingRecvMessage(grpc_error* error); + static void AfterCallStackDestruction(void* arg, grpc_error* error); + RefCountedPtr health_check_client_; grpc_polling_entity pollent_; @@ -126,12 +128,18 @@ class HealthCheckClient : public InternallyRefCounted { OrphanablePtr recv_message_; grpc_closure recv_message_ready_; grpc_slice_buffer recv_message_buffer_; - gpr_atm seen_response_; + Atomic seen_response_{false}; // recv_trailing_metadata grpc_metadata_batch recv_trailing_metadata_; grpc_transport_stream_stats collect_stats_; grpc_closure recv_trailing_metadata_ready_; + + // True if the cancel_stream batch has been started. + Atomic cancelled_{false}; + + // Closure for call stack destruction. + grpc_closure after_call_stack_destruction_; }; void StartCall(); diff --git a/src/core/ext/filters/client_channel/lb_policy.cc b/src/core/ext/filters/client_channel/lb_policy.cc index c8f8e82e5d7..6b657465891 100644 --- a/src/core/ext/filters/client_channel/lb_policy.cc +++ b/src/core/ext/filters/client_channel/lb_policy.cc @@ -140,10 +140,9 @@ LoadBalancingPolicy::PickResult LoadBalancingPolicy::QueuePicker::Pick( // the time this function returns, the pick will already have // been processed, and we'll be trying to re-process the same // pick again, leading to a crash. - // 2. In a subsequent PR, we will split the data plane and control - // plane synchronization into separate combiners, at which - // point this will need to hop from the data plane combiner into - // the control plane combiner. + // 2. We are currently running in the data plane combiner, but we + // need to bounce into the control plane combiner to call + // ExitIdleLocked(). if (!exit_idle_called_) { exit_idle_called_ = true; parent_->Ref().release(); // ref held by closure. diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc index 02fe06c4557..aebd2fd3faa 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc @@ -234,12 +234,19 @@ class GrpcLb : public LoadBalancingPolicy { // Returns the LB token to use for a drop, or null if the call // should not be dropped. - // Intended to be called from picker, so calls will be externally - // synchronized. + // + // Note: This is called from the picker, so it will be invoked in + // the channel's data plane combiner, NOT the control plane + // combiner. It should not be accessed by any other part of the LB + // policy. const char* ShouldDrop(); private: grpc_grpclb_serverlist* serverlist_; + + // Guarded by the channel's data plane combiner, NOT the control + // plane combiner. It should not be accessed by anything but the + // picker via the ShouldDrop() method. size_t drop_index_ = 0; }; @@ -551,7 +558,7 @@ GrpcLb::PickResult GrpcLb::Picker::Pick(PickArgs* pick, grpc_error** error) { // subchannel call (and therefore no client_load_reporting filter) // for dropped calls. if (client_stats_ != nullptr) { - client_stats_->AddCallDroppedLocked(drop_token); + client_stats_->AddCallDropped(drop_token); } return PICK_COMPLETE; } @@ -910,7 +917,7 @@ void GrpcLb::BalancerCallState::SendClientLoadReportLocked() { // Construct message payload. GPR_ASSERT(send_message_payload_ == nullptr); grpc_grpclb_request* request = - grpc_grpclb_load_report_request_create_locked(client_stats_.get()); + grpc_grpclb_load_report_request_create(client_stats_.get()); // Skip client load report if the counters were all zero in the last // report and they are still zero in this one. if (LoadReportCountersAreZero(request)) { diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc index 1c7ed871d74..84b9c41a734 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc @@ -25,6 +25,8 @@ #include #include +#include "src/core/lib/gprpp/mutex_lock.h" + namespace grpc_core { void GrpcLbClientStats::AddCallStarted() { @@ -43,11 +45,12 @@ void GrpcLbClientStats::AddCallFinished( } } -void GrpcLbClientStats::AddCallDroppedLocked(const char* token) { +void GrpcLbClientStats::AddCallDropped(const char* token) { // Increment num_calls_started and num_calls_finished. gpr_atm_full_fetch_add(&num_calls_started_, (gpr_atm)1); gpr_atm_full_fetch_add(&num_calls_finished_, (gpr_atm)1); // Record the drop. + MutexLock lock(&drop_count_mu_); if (drop_token_counts_ == nullptr) { drop_token_counts_.reset(New()); } @@ -69,7 +72,7 @@ void AtomicGetAndResetCounter(int64_t* value, gpr_atm* counter) { } // namespace -void GrpcLbClientStats::GetLocked( +void GrpcLbClientStats::Get( int64_t* num_calls_started, int64_t* num_calls_finished, int64_t* num_calls_finished_with_client_failed_to_send, int64_t* num_calls_finished_known_received, @@ -80,6 +83,7 @@ void GrpcLbClientStats::GetLocked( &num_calls_finished_with_client_failed_to_send_); AtomicGetAndResetCounter(num_calls_finished_known_received, &num_calls_finished_known_received_); + MutexLock lock(&drop_count_mu_); *drop_token_counts = std::move(drop_token_counts_); } diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h index cb261ee16c7..fdebdf55c17 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h @@ -41,20 +41,19 @@ class GrpcLbClientStats : public RefCounted { typedef InlinedVector DroppedCallCounts; - GrpcLbClientStats() {} + GrpcLbClientStats() { gpr_mu_init(&drop_count_mu_); } + ~GrpcLbClientStats() { gpr_mu_destroy(&drop_count_mu_); } void AddCallStarted(); void AddCallFinished(bool finished_with_client_failed_to_send, bool finished_known_received); - // This method is not thread-safe; caller must synchronize. - void AddCallDroppedLocked(const char* token); + void AddCallDropped(const char* token); - // This method is not thread-safe; caller must synchronize. - void GetLocked(int64_t* num_calls_started, int64_t* num_calls_finished, - int64_t* num_calls_finished_with_client_failed_to_send, - int64_t* num_calls_finished_known_received, - UniquePtr* drop_token_counts); + void Get(int64_t* num_calls_started, int64_t* num_calls_finished, + int64_t* num_calls_finished_with_client_failed_to_send, + int64_t* num_calls_finished_known_received, + UniquePtr* drop_token_counts); // A destruction function to use as the user_data key when attaching // client stats to a grpc_mdelem. @@ -63,13 +62,12 @@ class GrpcLbClientStats : public RefCounted { } private: - // This field must only be accessed via *_locked() methods. - UniquePtr drop_token_counts_; - // These fields may be accessed from multiple threads at a time. gpr_atm num_calls_started_ = 0; gpr_atm num_calls_finished_ = 0; gpr_atm num_calls_finished_with_client_failed_to_send_ = 0; gpr_atm num_calls_finished_known_received_ = 0; + gpr_mu drop_count_mu_; // Guards drop_token_counts_. + UniquePtr drop_token_counts_; }; } // namespace grpc_core diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc index 594c8cf6e94..b51db110395 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc @@ -107,7 +107,7 @@ static bool encode_drops(pb_ostream_t* stream, const pb_field_t* field, return true; } -grpc_grpclb_request* grpc_grpclb_load_report_request_create_locked( +grpc_grpclb_request* grpc_grpclb_load_report_request_create( grpc_core::GrpcLbClientStats* client_stats) { grpc_grpclb_request* req = static_cast( gpr_zalloc(sizeof(grpc_grpclb_request))); @@ -122,7 +122,7 @@ grpc_grpclb_request* grpc_grpclb_load_report_request_create_locked( req->client_stats.calls_finished_with_drop.funcs.encode = encode_drops; grpc_core::UniquePtr drop_counts; - client_stats->GetLocked( + client_stats->Get( &req->client_stats.num_calls_started, &req->client_stats.num_calls_finished, &req->client_stats.num_calls_finished_with_client_failed_to_send, diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h b/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h index 3c1d41a01b1..8005f6fe301 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h @@ -43,7 +43,7 @@ typedef struct { /** Create a request for a gRPC LB service under \a lb_service_name */ grpc_grpclb_request* grpc_grpclb_request_create(const char* lb_service_name); -grpc_grpclb_request* grpc_grpclb_load_report_request_create_locked( +grpc_grpclb_request* grpc_grpclb_load_report_request_create( grpc_core::GrpcLbClientStats* client_stats); /** Protocol Buffers v3-encode \a request */ diff --git a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc index 3da0b59f279..332f66808e0 100644 --- a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +++ b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc @@ -186,6 +186,7 @@ void PickFirst::ShutdownLocked() { } void PickFirst::ExitIdleLocked() { + if (shutdown_) return; if (idle_) { idle_ = false; if (subchannel_list_ == nullptr || diff --git a/src/cpp/client/generic_stub.cc b/src/cpp/client/generic_stub.cc index f61c1b5317b..41631c794f2 100644 --- a/src/cpp/client/generic_stub.cc +++ b/src/cpp/client/generic_stub.cc @@ -22,63 +22,75 @@ #include #include -namespace grpc { +namespace grpc_impl { namespace { -std::unique_ptr CallInternal( - ChannelInterface* channel, ClientContext* context, - const grpc::string& method, CompletionQueue* cq, bool start, void* tag) { - return std::unique_ptr( - internal::ClientAsyncReaderWriterFactory::Create( - channel, cq, - internal::RpcMethod(method.c_str(), - internal::RpcMethod::BIDI_STREAMING), - context, start, tag)); +std::unique_ptr CallInternal( + grpc::ChannelInterface* channel, grpc::ClientContext* context, + const grpc::string& method, grpc::CompletionQueue* cq, bool start, + void* tag) { + return std::unique_ptr( + grpc::internal::ClientAsyncReaderWriterFactory:: + Create(channel, cq, + grpc::internal::RpcMethod( + method.c_str(), grpc::internal::RpcMethod::BIDI_STREAMING), + context, start, tag)); } } // namespace // begin a call to a named method -std::unique_ptr GenericStub::Call( - ClientContext* context, const grpc::string& method, CompletionQueue* cq, - void* tag) { +std::unique_ptr GenericStub::Call( + grpc::ClientContext* context, const grpc::string& method, + grpc::CompletionQueue* cq, void* tag) { return CallInternal(channel_.get(), context, method, cq, true, tag); } // setup a call to a named method -std::unique_ptr GenericStub::PrepareCall( - ClientContext* context, const grpc::string& method, CompletionQueue* cq) { +std::unique_ptr GenericStub::PrepareCall( + grpc::ClientContext* context, const grpc::string& method, + grpc::CompletionQueue* cq) { return CallInternal(channel_.get(), context, method, cq, false, nullptr); } // setup a unary call to a named method -std::unique_ptr GenericStub::PrepareUnaryCall( - ClientContext* context, const grpc::string& method, - const ByteBuffer& request, CompletionQueue* cq) { - return std::unique_ptr( - internal::ClientAsyncResponseReaderFactory::Create( - channel_.get(), cq, - internal::RpcMethod(method.c_str(), internal::RpcMethod::NORMAL_RPC), - context, request, false)); +std::unique_ptr +GenericStub::PrepareUnaryCall(grpc::ClientContext* context, + const grpc::string& method, + const grpc::ByteBuffer& request, + grpc::CompletionQueue* cq) { + return std::unique_ptr( + grpc::internal::ClientAsyncResponseReaderFactory< + grpc::ByteBuffer>::Create(channel_.get(), cq, + grpc::internal::RpcMethod( + method.c_str(), + grpc::internal::RpcMethod::NORMAL_RPC), + context, request, false)); } void GenericStub::experimental_type::UnaryCall( - ClientContext* context, const grpc::string& method, - const ByteBuffer* request, ByteBuffer* response, - std::function on_completion) { - internal::CallbackUnaryCall( + grpc::ClientContext* context, const grpc::string& method, + const grpc::ByteBuffer* request, grpc::ByteBuffer* response, + std::function on_completion) { + grpc::internal::CallbackUnaryCall( stub_->channel_.get(), - internal::RpcMethod(method.c_str(), internal::RpcMethod::NORMAL_RPC), + grpc::internal::RpcMethod(method.c_str(), + grpc::internal::RpcMethod::NORMAL_RPC), context, request, response, std::move(on_completion)); } void GenericStub::experimental_type::PrepareBidiStreamingCall( - ClientContext* context, const grpc::string& method, - experimental::ClientBidiReactor* reactor) { - internal::ClientCallbackReaderWriterFactory::Create( - stub_->channel_.get(), - internal::RpcMethod(method.c_str(), internal::RpcMethod::BIDI_STREAMING), - context, reactor); + grpc::ClientContext* context, const grpc::string& method, + grpc::experimental::ClientBidiReactor* + reactor) { + grpc::internal::ClientCallbackReaderWriterFactory< + grpc::ByteBuffer, + grpc::ByteBuffer>::Create(stub_->channel_.get(), + grpc::internal::RpcMethod( + method.c_str(), + grpc::internal::RpcMethod::BIDI_STREAMING), + context, reactor); } -} // namespace grpc +} // namespace grpc_impl diff --git a/src/cpp/ext/proto_server_reflection_plugin.cc b/src/cpp/ext/proto_server_reflection_plugin.cc index ee3ac3fee88..0ac4cb80c64 100644 --- a/src/cpp/ext/proto_server_reflection_plugin.cc +++ b/src/cpp/ext/proto_server_reflection_plugin.cc @@ -23,7 +23,7 @@ #include "src/cpp/ext/proto_server_reflection.h" -namespace grpc { +namespace grpc_impl { namespace reflection { ProtoServerReflectionPlugin::ProtoServerReflectionPlugin() @@ -79,4 +79,4 @@ struct StaticProtoReflectionPluginInitializer { } static_proto_reflection_plugin_initializer; } // namespace reflection -} // namespace grpc +} // namespace grpc_impl diff --git a/src/cpp/server/insecure_server_credentials.cc b/src/cpp/server/insecure_server_credentials.cc index 7d749ddca4d..e4623ececef 100644 --- a/src/cpp/server/insecure_server_credentials.cc +++ b/src/cpp/server/insecure_server_credentials.cc @@ -21,7 +21,7 @@ #include #include -namespace grpc { +namespace grpc_impl { namespace { class InsecureServerCredentialsImpl final : public ServerCredentials { public: @@ -29,7 +29,7 @@ class InsecureServerCredentialsImpl final : public ServerCredentials { return grpc_server_add_insecure_http2_port(server, addr.c_str()); } void SetAuthMetadataProcessor( - const std::shared_ptr& processor) override { + const std::shared_ptr& processor) override { (void)processor; GPR_ASSERT(0); // Should not be called on InsecureServerCredentials. } @@ -41,4 +41,4 @@ std::shared_ptr InsecureServerCredentials() { new InsecureServerCredentialsImpl()); } -} // namespace grpc +} // namespace grpc_impl diff --git a/src/cpp/server/secure_server_credentials.cc b/src/cpp/server/secure_server_credentials.cc index 453e76eb25d..93dc10f14ea 100644 --- a/src/cpp/server/secure_server_credentials.cc +++ b/src/cpp/server/secure_server_credentials.cc @@ -93,21 +93,25 @@ void AuthMetadataProcessorAyncWrapper::InvokeProcessor( status.error_message().c_str()); } +} // namespace grpc + +namespace grpc_impl { + int SecureServerCredentials::AddPortToServer(const grpc::string& addr, grpc_server* server) { return grpc_server_add_secure_http2_port(server, addr.c_str(), creds_); } void SecureServerCredentials::SetAuthMetadataProcessor( - const std::shared_ptr& processor) { - auto* wrapper = new AuthMetadataProcessorAyncWrapper(processor); + const std::shared_ptr& processor) { + auto* wrapper = new grpc::AuthMetadataProcessorAyncWrapper(processor); grpc_server_credentials_set_auth_metadata_processor( - creds_, {AuthMetadataProcessorAyncWrapper::Process, - AuthMetadataProcessorAyncWrapper::Destroy, wrapper}); + creds_, {grpc::AuthMetadataProcessorAyncWrapper::Process, + grpc::AuthMetadataProcessorAyncWrapper::Destroy, wrapper}); } std::shared_ptr SslServerCredentials( - const SslServerCredentialsOptions& options) { + const grpc::SslServerCredentialsOptions& options) { std::vector pem_key_cert_pairs; for (auto key_cert_pair = options.pem_key_cert_pairs.begin(); key_cert_pair != options.pem_key_cert_pairs.end(); key_cert_pair++) { @@ -147,4 +151,4 @@ std::shared_ptr LocalServerCredentials( } } // namespace experimental -} // namespace grpc +} // namespace grpc_impl diff --git a/src/cpp/server/secure_server_credentials.h b/src/cpp/server/secure_server_credentials.h index 8a81af2f591..24b133cf7f0 100644 --- a/src/cpp/server/secure_server_credentials.h +++ b/src/cpp/server/secure_server_credentials.h @@ -27,8 +27,15 @@ #include "src/cpp/server/thread_pool_interface.h" +namespace grpc_impl { + +class SecureServerCredentials; +} // namespace grpc_impl + namespace grpc { +typedef ::grpc_impl::SecureServerCredentials SecureServerCredentials; + class AuthMetadataProcessorAyncWrapper final { public: static void Destroy(void* wrapper); @@ -49,6 +56,10 @@ class AuthMetadataProcessorAyncWrapper final { std::shared_ptr processor_; }; +} // namespace grpc + +namespace grpc_impl { + class SecureServerCredentials final : public ServerCredentials { public: explicit SecureServerCredentials(grpc_server_credentials* creds) @@ -60,13 +71,13 @@ class SecureServerCredentials final : public ServerCredentials { int AddPortToServer(const grpc::string& addr, grpc_server* server) override; void SetAuthMetadataProcessor( - const std::shared_ptr& processor) override; + const std::shared_ptr& processor) override; private: grpc_server_credentials* creds_; - std::unique_ptr processor_; + std::unique_ptr processor_; }; -} // namespace grpc +} // namespace grpc_impl #endif // GRPC_INTERNAL_CPP_SERVER_SECURE_SERVER_CREDENTIALS_H diff --git a/src/cpp/server/server_credentials.cc b/src/cpp/server/server_credentials.cc index c3b3a8b3793..8b85264f9d7 100644 --- a/src/cpp/server/server_credentials.cc +++ b/src/cpp/server/server_credentials.cc @@ -16,10 +16,10 @@ * */ -#include +#include -namespace grpc { +namespace grpc_impl { ServerCredentials::~ServerCredentials() {} -} // namespace grpc +} // namespace grpc_impl diff --git a/templates/grpc.gemspec.template b/templates/grpc.gemspec.template index 0e321717c99..d2b54a9c2f5 100644 --- a/templates/grpc.gemspec.template +++ b/templates/grpc.gemspec.template @@ -32,7 +32,7 @@ s.platform = Gem::Platform::RUBY s.add_dependency 'google-protobuf', '~> 3.7' - s.add_dependency 'googleapis-common-protos-types', '~> 1.0.0' + s.add_dependency 'googleapis-common-protos-types', '~> 1.0' s.add_development_dependency 'bundler', '~> 1.9' s.add_development_dependency 'facter', '~> 2.4' diff --git a/test/cpp/end2end/cfstream_test.cc b/test/cpp/end2end/cfstream_test.cc index a6ed7c66d84..63d76e96f8b 100644 --- a/test/cpp/end2end/cfstream_test.cc +++ b/test/cpp/end2end/cfstream_test.cc @@ -62,7 +62,7 @@ class CFStreamTest : public ::testing::Test { CFStreamTest() : server_host_("grpctest"), interface_("lo0"), - ipv4_address_("127.0.0.2"), + ipv4_address_("10.0.0.1"), kRequestMessage_("🖖") {} void DNSUp() { diff --git a/test/cpp/util/test_credentials_provider.cc b/test/cpp/util/test_credentials_provider.cc index 0cf75f1e5f1..49688e5cf9b 100644 --- a/test/cpp/util/test_credentials_provider.cc +++ b/test/cpp/util/test_credentials_provider.cc @@ -24,6 +24,7 @@ #include #include +#include #include "test/core/end2end/data/ssl_test_data.h" diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 7dbb63813c2..a56d2df8530 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -936,6 +936,7 @@ include/grpcpp/create_channel_posix_impl.h \ include/grpcpp/ext/health_check_service_server_builder_option.h \ include/grpcpp/generic/async_generic_service.h \ include/grpcpp/generic/generic_stub.h \ +include/grpcpp/generic/generic_stub_impl.h \ include/grpcpp/grpcpp.h \ include/grpcpp/health_check_service_interface.h \ include/grpcpp/health_check_service_interface_impl.h \ @@ -1006,6 +1007,7 @@ include/grpcpp/security/auth_metadata_processor.h \ include/grpcpp/security/auth_metadata_processor_impl.h \ include/grpcpp/security/credentials.h \ include/grpcpp/security/server_credentials.h \ +include/grpcpp/security/server_credentials_impl.h \ include/grpcpp/server.h \ include/grpcpp/server_builder.h \ include/grpcpp/server_context.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index c7d29b228ab..6bf498307bb 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -937,6 +937,7 @@ include/grpcpp/create_channel_posix_impl.h \ include/grpcpp/ext/health_check_service_server_builder_option.h \ include/grpcpp/generic/async_generic_service.h \ include/grpcpp/generic/generic_stub.h \ +include/grpcpp/generic/generic_stub_impl.h \ include/grpcpp/grpcpp.h \ include/grpcpp/health_check_service_interface.h \ include/grpcpp/health_check_service_interface_impl.h \ @@ -1008,6 +1009,7 @@ include/grpcpp/security/auth_metadata_processor.h \ include/grpcpp/security/auth_metadata_processor_impl.h \ include/grpcpp/security/credentials.h \ include/grpcpp/security/server_credentials.h \ +include/grpcpp/security/server_credentials_impl.h \ include/grpcpp/server.h \ include/grpcpp/server_builder.h \ include/grpcpp/server_context.h \ diff --git a/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh b/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh index 1882fe213fa..dd34eac7b38 100755 --- a/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh +++ b/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh @@ -23,7 +23,7 @@ cp ${KOKORO_GFILE_DIR}/GrpcTesting-d0eeee2db331.json ${KOKORO_KEYSTORE_DIR}/4321 # Download bazel temp_dir="$(mktemp -d)" -wget -q https://github.com/bazelbuild/bazel/releases/download/0.22.0/bazel-0.22.0-linux-x86_64 -O "${temp_dir}/bazel" +wget -q https://github.com/bazelbuild/bazel/releases/download/0.23.2/bazel-0.23.2-linux-x86_64 -O "${temp_dir}/bazel" chmod 755 "${temp_dir}/bazel" export PATH="${temp_dir}:${PATH}" # This should show ${temp_dir}/bazel diff --git a/tools/release/release_notes.py b/tools/release/release_notes.py new file mode 100644 index 00000000000..46e01843535 --- /dev/null +++ b/tools/release/release_notes.py @@ -0,0 +1,369 @@ +#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. +"""Generate draft and release notes in Markdown from Github PRs. + +You'll need a github API token to avoid being rate-limited. See +https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/ + +This script collects PRs using "git log X..Y" from local repo where X and Y are +tags or release branch names of previous and current releases respectively. +Typically, notes are generated before the release branch is labelled so Y is +almost always the name of the release branch. X is the previous release branch +if this is not a patch release. Otherwise, it is the previous release tag. +For example, for release v1.17.0, X will be origin/v1.16.x and for release v1.17.3, +X will be v1.17.2. In both cases Y will be origin/v1.17.x. + +""" + +from collections import defaultdict +import base64 +import json + +content_header = """Draft Release Notes For {version} +-- +Final release notes will be generated from the PR titles that have *"release notes:yes"* label. If you have any additional notes please add them below. These will be appended to auto generated release notes. Previous releases notes are [here](https://github.com/grpc/grpc/releases). + +**Also, look at the PRs listed below against your name.** Please apply the missing labels and make necessary corrections (like fixing the title) to the PR in Github. Final release notes will be generated just before the release on {date}. + +Add additional notes not in PRs +-- + +Core +- + + +C++ +- + + +C# +- + + +Objective-C +- + + +PHP +- + + +Python +- + + +Ruby +- + + +""" + +rl_header = """This is the {version} release ([{name}](https://github.com/grpc/grpc/blob/master/doc/g_stands_for.md)) of gRPC Core. + +Please see the notes for the previous releases here: https://github.com/grpc/grpc/releases. Please consult https://grpc.io/ for all information regarding this product. + +This release contains refinements, improvements, and bug fixes, with highlights listed below. + + +""" + +HTML_URL = "https://github.com/grpc/grpc/pull/" +API_URL = 'https://api.github.com/repos/grpc/grpc/pulls/' + + +def get_commit_log(prevRelLabel, relBranch): + """Return the output of 'git log --pretty=online --merges prevRelLabel..relBranch' """ + + import subprocess + print("Running git log --pretty=oneline --merges " + prevRelLabel + ".." + + relBranch) + return subprocess.check_output([ + "git", "log", "--pretty=oneline", "--merges", + "%s..%s" % (prevRelLabel, relBranch) + ]) + + +def get_pr_data(pr_num): + """Get the PR data from github. Return 'error' on exception""" + + try: + from urllib2 import Request, urlopen, HTTPError + except ImportError: + import urllib + from urllib.request import Request, urlopen, HTTPError + url = API_URL + pr_num + req = Request(url) + req.add_header('Authorization', 'token %s' % TOKEN) + try: + f = urlopen(req) + response = json.loads(f.read().decode('utf-8')) + #print(response) + except HTTPError as e: + response = json.loads(e.fp.read().decode('utf-8')) + if 'message' in response: + print(response['message']) + response = "error" + return response + + +def get_pr_titles(gitLogs): + import re + error_count = 0 + match = b"Merge pull request #(\d+)" + prlist = re.findall(match, gitLogs, re.MULTILINE) + print("\nPRs matching 'Merge pull request #':") + print(prlist) + print("\n") + langs_pr = defaultdict(list) + for pr_num in prlist: + pr_num = str(pr_num) + print("---------- getting data for PR " + pr_num) + pr = get_pr_data(pr_num) + if pr == "error": + print("\n***ERROR*** Error in getting data for PR " + pr_num + "\n") + error_count += 1 + continue + rl_no_found = False + rl_yes_found = False + lang_found = False + for label in pr['labels']: + if label['name'] == 'release notes: yes': + rl_yes_found = True + elif label['name'] == 'release notes: no': + rl_no_found = True + elif label['name'].startswith('lang/'): + lang_found = True + lang = label['name'].split('/')[1].lower() + #lang = lang[0].upper() + lang[1:] + body = pr["title"] + if not body.endswith("."): + body = body + "." + if not pr["merged_by"]: + print("\n***ERROR***: No merge_by found for PR " + pr_num + "\n") + error_count += 1 + continue + + prline = "- " + body + " ([#" + pr_num + "](" + HTML_URL + pr_num + "))" + detail = "- " + pr["merged_by"]["login"] + "@ " + prline + prline = prline.encode('ascii', 'ignore') + detail = detail.encode('ascii', 'ignore') + print(detail) + #if no RL label + if not rl_no_found and not rl_yes_found: + print("Release notes label missing for " + pr_num) + langs_pr["nolabel"].append(detail) + elif rl_yes_found and not lang_found: + print("Lang label missing for " + pr_num) + langs_pr["nolang"].append(detail) + elif rl_no_found: + print("'Release notes:no' found for " + pr_num) + langs_pr["notinrel"].append(detail) + elif rl_yes_found: + print("'Release notes:yes' found for " + pr_num + " with lang " + + lang) + langs_pr["inrel"].append(detail) + langs_pr[lang].append(prline) + + return langs_pr, error_count + + +def write_draft(langs_pr, file, version, date): + file.write(content_header.format(version=version, date=date)) + file.write("PRs with missing release notes label - please fix in Github\n") + file.write("---\n") + file.write("\n") + if langs_pr["nolabel"]: + langs_pr["nolabel"].sort() + file.write("\n".join(langs_pr["nolabel"])) + else: + file.write("- None") + file.write("\n") + file.write("\n") + file.write("PRs with missing lang label - please fix in Github\n") + file.write("---\n") + file.write("\n") + if langs_pr["nolang"]: + langs_pr["nolang"].sort() + file.write("\n".join(langs_pr["nolang"])) + else: + file.write("- None") + file.write("\n") + file.write("\n") + file.write( + "PRs going into release notes - please check title and fix in Github. Do not edit here.\n" + ) + file.write("---\n") + file.write("\n") + if langs_pr["inrel"]: + langs_pr["inrel"].sort() + file.write("\n".join(langs_pr["inrel"])) + else: + file.write("- None") + file.write("\n") + file.write("\n") + file.write("PRs not going into release notes\n") + file.write("---\n") + file.write("\n") + if langs_pr["notinrel"]: + langs_pr["notinrel"].sort() + file.write("\n".join(langs_pr["notinrel"])) + else: + file.write("- None") + file.write("\n") + file.write("\n") + + +def write_rel_notes(langs_pr, file, version, name): + file.write(rl_header.format(version=version, name=name)) + if langs_pr["core"]: + file.write("Core\n---\n\n") + file.write("\n".join(langs_pr["core"])) + file.write("\n") + file.write("\n") + if langs_pr["c++"]: + file.write("C++\n---\n\n") + file.write("\n".join(langs_pr["c++"])) + file.write("\n") + file.write("\n") + if langs_pr["c#"]: + file.write("C#\n---\n\n") + file.write("\n".join(langs_pr["c#"])) + file.write("\n") + file.write("\n") + if langs_pr["go"]: + file.write("Go\n---\n\n") + file.write("\n".join(langs_pr["go"])) + file.write("\n") + file.write("\n") + if langs_pr["Java"]: + file.write("Java\n---\n\n") + file.write("\n".join(langs_pr["Java"])) + file.write("\n") + file.write("\n") + if langs_pr["node"]: + file.write("Node\n---\n\n") + file.write("\n".join(langs_pr["node"])) + file.write("\n") + file.write("\n") + if langs_pr["objc"]: + file.write("Objective-C\n---\n\n") + file.write("\n".join(langs_pr["objc"])) + file.write("\n") + file.write("\n") + if langs_pr["php"]: + file.write("PHP\n---\n\n") + file.write("\n".join(langs_pr["php"])) + file.write("\n") + file.write("\n") + if langs_pr["python"]: + file.write("Python\n---\n\n") + file.write("\n".join(langs_pr["python"])) + file.write("\n") + file.write("\n") + if langs_pr["ruby"]: + file.write("Ruby\n---\n\n") + file.write("\n".join(langs_pr["ruby"])) + file.write("\n") + file.write("\n") + if langs_pr["other"]: + file.write("Other\n---\n\n") + file.write("\n".join(langs_pr["other"])) + file.write("\n") + file.write("\n") + + +def build_args_parser(): + import argparse + parser = argparse.ArgumentParser() + parser.add_argument( + 'release_version', type=str, help='New release version e.g. 1.14.0') + parser.add_argument( + 'release_name', type=str, help='New release name e.g. gladiolus') + parser.add_argument( + 'release_date', type=str, help='Release date e.g. 7/30/18') + parser.add_argument( + 'previous_release_label', + type=str, + help='Previous release branch/tag e.g. v1.13.x') + parser.add_argument( + 'release_branch', + type=str, + help='Current release branch e.g. origin/v1.14.x') + parser.add_argument( + 'draft_filename', type=str, help='Name of the draft file e.g. draft.md') + parser.add_argument( + 'release_notes_filename', + type=str, + help='Name of the release notes file e.g. relnotes.md') + parser.add_argument( + '--token', + type=str, + default='', + help='GitHub API token to avoid being rate limited') + return parser + + +def main(): + import os + global TOKEN + + parser = build_args_parser() + args = parser.parse_args() + version, name, date = args.release_version, args.release_name, args.release_date + start, end = args.previous_release_label, args.release_branch + + TOKEN = args.token + if TOKEN == '': + try: + TOKEN = os.environ["GITHUB_TOKEN"] + except: + pass + if TOKEN == '': + print( + "Error: Github API token required. Either include param --token= or set environment variable GITHUB_TOKEN to your github token" + ) + return + + langs_pr, error_count = get_pr_titles(get_commit_log(start, end)) + + draft_file, rel_file = args.draft_filename, args.release_notes_filename + filename = os.path.abspath(draft_file) + if os.path.exists(filename): + file = open(filename, 'r+') + else: + file = open(filename, 'w') + + file.seek(0) + write_draft(langs_pr, file, version, date) + file.truncate() + file.close() + print("\nDraft notes written to " + filename) + + filename = os.path.abspath(rel_file) + if os.path.exists(filename): + file = open(filename, 'r+') + else: + file = open(filename, 'w') + + file.seek(0) + write_rel_notes(langs_pr, file, version, name) + file.truncate() + file.close() + print("\nRelease notes written to " + filename) + if error_count > 0: + print("\n\n*** Errors were encountered. See log. *********\n") + + +if __name__ == "__main__": + main() diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 7a5d92abdaa..71e2b0d2207 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -6652,6 +6652,7 @@ "headers": [ "include/grpc++/ext/proto_server_reflection_plugin.h", "include/grpcpp/ext/proto_server_reflection_plugin.h", + "include/grpcpp/ext/proto_server_reflection_plugin_impl.h", "src/cpp/ext/proto_server_reflection.h" ], "is_filegroup": false, @@ -6660,6 +6661,7 @@ "src": [ "include/grpc++/ext/proto_server_reflection_plugin.h", "include/grpcpp/ext/proto_server_reflection_plugin.h", + "include/grpcpp/ext/proto_server_reflection_plugin_impl.h", "src/cpp/ext/proto_server_reflection.cc", "src/cpp/ext/proto_server_reflection.h", "src/cpp/ext/proto_server_reflection_plugin.cc" @@ -10099,6 +10101,7 @@ "include/grpcpp/ext/health_check_service_server_builder_option.h", "include/grpcpp/generic/async_generic_service.h", "include/grpcpp/generic/generic_stub.h", + "include/grpcpp/generic/generic_stub_impl.h", "include/grpcpp/grpcpp.h", "include/grpcpp/health_check_service_interface.h", "include/grpcpp/health_check_service_interface_impl.h", @@ -10124,6 +10127,7 @@ "include/grpcpp/security/auth_metadata_processor_impl.h", "include/grpcpp/security/credentials.h", "include/grpcpp/security/server_credentials.h", + "include/grpcpp/security/server_credentials_impl.h", "include/grpcpp/server.h", "include/grpcpp/server_builder.h", "include/grpcpp/server_context.h", @@ -10216,6 +10220,7 @@ "include/grpcpp/ext/health_check_service_server_builder_option.h", "include/grpcpp/generic/async_generic_service.h", "include/grpcpp/generic/generic_stub.h", + "include/grpcpp/generic/generic_stub_impl.h", "include/grpcpp/grpcpp.h", "include/grpcpp/health_check_service_interface.h", "include/grpcpp/health_check_service_interface_impl.h", @@ -10241,6 +10246,7 @@ "include/grpcpp/security/auth_metadata_processor_impl.h", "include/grpcpp/security/credentials.h", "include/grpcpp/security/server_credentials.h", + "include/grpcpp/security/server_credentials_impl.h", "include/grpcpp/server.h", "include/grpcpp/server_builder.h", "include/grpcpp/server_context.h",