diff --git a/include/grpcpp/impl/codegen/server_context_impl.h b/include/grpcpp/impl/codegen/server_context_impl.h index 25673c63811..197bf98dc66 100644 --- a/include/grpcpp/impl/codegen/server_context_impl.h +++ b/include/grpcpp/impl/codegen/server_context_impl.h @@ -95,10 +95,13 @@ namespace grpc { class GenericServerContext; class ServerInterface; +#ifndef GRPC_CALLBACK_API_NONEXPERIMENTAL namespace experimental { +#endif class GenericCallbackServerContext; +#ifndef GRPC_CALLBACK_API_NONEXPERIMENTAL } // namespace experimental - +#endif namespace internal { class Call; } // namespace internal @@ -348,7 +351,11 @@ class ServerContextBase { friend class ::grpc_impl::internal::FinishOnlyReactor; friend class ::grpc_impl::ClientContext; friend class ::grpc::GenericServerContext; +#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + friend class ::grpc::GenericCallbackServerContext; +#else friend class ::grpc::experimental::GenericCallbackServerContext; +#endif /// Prevent copying. ServerContextBase(const ServerContextBase&); diff --git a/include/grpcpp/impl/codegen/server_interface.h b/include/grpcpp/impl/codegen/server_interface.h index 4431554ef3b..105baf80bbf 100644 --- a/include/grpcpp/impl/codegen/server_interface.h +++ b/include/grpcpp/impl/codegen/server_interface.h @@ -51,8 +51,15 @@ namespace internal { class ServerAsyncStreamingInterface; } // namespace internal +#ifndef GRPC_CALLBACK_API_NONEXPERIMENTAL namespace experimental { +#endif class CallbackGenericService; +#ifndef GRPC_CALLBACK_API_NONEXPERIMENTAL +} // namespace experimental +#endif + +namespace experimental { class ServerInterceptorFactoryInterface; } // namespace experimental @@ -124,6 +131,14 @@ class ServerInterface : public internal::CallHook { /// service. The service must exist for the lifetime of the Server instance. virtual void RegisterAsyncGenericService(AsyncGenericService* service) = 0; +#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + /// Register a callback generic service. This call does not take ownership of + /// the service. The service must exist for the lifetime of the Server + /// instance. May not be abstract since this is a post-1.0 API addition. + + virtual void RegisterCallbackGenericService(CallbackGenericService* + /*service*/) {} +#else /// NOTE: class experimental_registration_interface is not part of the public /// API of this class /// TODO(vjpai): Move these contents to public API when no longer experimental @@ -142,6 +157,7 @@ class ServerInterface : public internal::CallHook { virtual experimental_registration_interface* experimental_registration() { return nullptr; } +#endif /// Tries to bind \a server to the given \a addr. /// diff --git a/include/grpcpp/server_builder_impl.h b/include/grpcpp/server_builder_impl.h index 7f85e807d07..501dfeba51d 100644 --- a/include/grpcpp/server_builder_impl.h +++ b/include/grpcpp/server_builder_impl.h @@ -57,9 +57,15 @@ namespace internal { class ExternalConnectionAcceptorImpl; } // namespace internal +#ifndef GRPC_CALLBACK_API_NONEXPERIMENTAL namespace experimental { +#endif class CallbackGenericService; +#ifndef GRPC_CALLBACK_API_NONEXPERIMENTAL +} // namespace experimental +#endif +namespace experimental { // EXPERIMENTAL API: // Interface for a grpc server to build transports with connections created out // of band. @@ -265,12 +271,14 @@ class ServerBuilder { builder_->interceptor_creators_ = std::move(interceptor_creators); } +#ifndef GRPC_CALLBACK_API_NONEXPERIMENTAL /// Register a generic service that uses the callback API. /// Matches requests with any :authority /// This is mostly useful for writing generic gRPC Proxies where the exact /// serialization format is unknown ServerBuilder& RegisterCallbackGenericService( grpc::experimental::CallbackGenericService* service); +#endif enum class ExternalConnectionType { FROM_FD = 0 // in the form of a file descriptor @@ -288,6 +296,15 @@ class ServerBuilder { ServerBuilder* builder_; }; +#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + /// Register a generic service that uses the callback API. + /// Matches requests with any :authority + /// This is mostly useful for writing generic gRPC Proxies where the exact + /// serialization format is unknown + ServerBuilder& RegisterCallbackGenericService( + grpc::CallbackGenericService* service); +#endif + /// 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. @@ -369,8 +386,13 @@ class ServerBuilder { std::vector> plugins_; grpc_resource_quota* resource_quota_; grpc::AsyncGenericService* generic_service_{nullptr}; +#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + grpc::CallbackGenericService* callback_generic_service_{nullptr}; +#else grpc::experimental::CallbackGenericService* callback_generic_service_{ nullptr}; +#endif + struct { bool is_set; grpc_compression_level level; diff --git a/include/grpcpp/server_impl.h b/include/grpcpp/server_impl.h index bb9380ad532..505800f3ccf 100644 --- a/include/grpcpp/server_impl.h +++ b/include/grpcpp/server_impl.h @@ -243,6 +243,13 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen { /// service. The service must exist for the lifetime of the Server instance. void RegisterAsyncGenericService(grpc::AsyncGenericService* service) override; +#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + /// Register a callback-based generic service. This call does not take + /// ownership of theservice. The service must exist for the lifetime of the + /// Server instance. + void RegisterCallbackGenericService( + grpc::CallbackGenericService* service) override; +#else /// NOTE: class experimental_registration_type is not part of the public API /// of this class /// TODO(vjpai): Move these contents to the public API of Server when @@ -270,6 +277,7 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen { experimental_registration_interface* experimental_registration() override { return &experimental_registration_; } +#endif void PerformOpsOnCall(grpc::internal::CallOpSetInterface* ops, grpc::internal::Call* call) override; @@ -318,9 +326,11 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen { // List of callback requests to start when server actually starts. std::list callback_reqs_to_start_; +#ifndef GRPC_CALLBACK_API_NONEXPERIMENTAL // For registering experimental callback generic service; remove when that // method longer experimental experimental_registration_type experimental_registration_{this}; +#endif // Server status grpc::internal::Mutex mu_; @@ -357,8 +367,12 @@ class Server : public grpc::ServerInterface, private grpc::GrpcLibraryCodegen { // When appropriate, use a default callback generic service to handle // unimplemented methods +#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + std::unique_ptr unimplemented_service_; +#else std::unique_ptr unimplemented_service_; +#endif // A special handler for resource exhausted in sync case std::unique_ptr resource_exhausted_handler_; diff --git a/src/cpp/server/server_builder.cc b/src/cpp/server/server_builder.cc index dffcad0c549..c058a75dc03 100644 --- a/src/cpp/server/server_builder.cc +++ b/src/cpp/server/server_builder.cc @@ -101,6 +101,20 @@ ServerBuilder& ServerBuilder::RegisterAsyncGenericService( return *this; } +#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL +ServerBuilder& ServerBuilder::RegisterCallbackGenericService( + grpc::CallbackGenericService* service) { + if (generic_service_ || callback_generic_service_) { + gpr_log(GPR_ERROR, + "Adding multiple generic services is unsupported for now. " + "Dropping the service %p", + (void*)service); + } else { + callback_generic_service_ = service; + } + return *this; +} +#else ServerBuilder& ServerBuilder::experimental_type::RegisterCallbackGenericService( grpc::experimental::CallbackGenericService* service) { if (builder_->generic_service_ || builder_->callback_generic_service_) { @@ -113,6 +127,7 @@ ServerBuilder& ServerBuilder::experimental_type::RegisterCallbackGenericService( } return *builder_; } +#endif std::unique_ptr ServerBuilder::experimental_type::AddExternalConnectionAcceptor( diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index 64330d296d1..f658ef64bee 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -106,6 +106,14 @@ class UnimplementedAsyncRequestContext { GenericServerAsyncReaderWriter generic_stream_; }; +// TODO(b/142832583): Just for this file, use some contents of the experimental +// namespace here to make the code easier to read below. Remove this when +// de-experimentalized fully. +#ifndef GRPC_CALLBACK_API_NONEXPERIMENTAL +using ::grpc::experimental::CallbackGenericService; +using ::grpc::experimental::GenericCallbackServerContext; +#endif + } // namespace ServerInterface::BaseAsyncRequest::BaseAsyncRequest( @@ -805,8 +813,9 @@ bool Server::CallbackRequest:: } template <> -bool Server::CallbackRequest:: - FinalizeResult(void** /*tag*/, bool* status) { +bool Server::CallbackRequest< + grpc::GenericCallbackServerContext>::FinalizeResult(void** /*tag*/, + bool* status) { if (*status) { // TODO(yangg) remove the copy here ctx_.method_ = grpc::StringFromCopiedSlice(call_details_->method); @@ -825,7 +834,7 @@ const char* Server::CallbackRequest< template <> const char* Server::CallbackRequest< - grpc::experimental::GenericCallbackServerContext>::method_name() const { + grpc::GenericCallbackServerContext>::method_name() const { return ctx_.method().c_str(); } @@ -1161,7 +1170,7 @@ void Server::RegisterAsyncGenericService(grpc::AsyncGenericService* service) { } void Server::RegisterCallbackGenericService( - grpc::experimental::CallbackGenericService* service) { + grpc::CallbackGenericService* service) { GPR_ASSERT( service->server_ == nullptr && "Can only register a callback generic service against one server."); @@ -1174,7 +1183,7 @@ void Server::RegisterCallbackGenericService( // TODO(vjpai): Register these dynamically based on need for (int i = 0; i < DEFAULT_CALLBACK_REQS_PER_METHOD; i++) { callback_reqs_to_start_.push_back( - new CallbackRequest( + new CallbackRequest( this, method_index, nullptr, nullptr)); } } @@ -1223,8 +1232,7 @@ void Server::Start(grpc::ServerCompletionQueue** cqs, size_t num_cqs) { // service to handle any unimplemented methods using the default reactor // creator if (!callback_reqs_to_start_.empty() && !has_callback_generic_service_) { - unimplemented_service_.reset( - new grpc::experimental::CallbackGenericService); + unimplemented_service_.reset(new grpc::CallbackGenericService); RegisterCallbackGenericService(unimplemented_service_.get()); } diff --git a/test/cpp/end2end/hybrid_end2end_test.cc b/test/cpp/end2end/hybrid_end2end_test.cc index 0314ed251e2..72214cfe44c 100644 --- a/test/cpp/end2end/hybrid_end2end_test.cc +++ b/test/cpp/end2end/hybrid_end2end_test.cc @@ -43,6 +43,12 @@ namespace grpc { namespace testing { namespace { +#ifndef GRPC_CALLBACK_API_NONEXPERIMENTAL +using ::grpc::experimental::CallbackGenericService; +using ::grpc::experimental::GenericCallbackServerContext; +using ::grpc::experimental::ServerGenericBidiReactor; +#endif + void* tag(int i) { return (void*)static_cast(i); } bool VerifyReturnSuccess(CompletionQueue* cq, int i) { @@ -245,11 +251,10 @@ class HybridEnd2endTest : public ::testing::TestWithParam { : false; } - bool SetUpServer( - ::grpc::Service* service1, ::grpc::Service* service2, - AsyncGenericService* generic_service, - experimental::CallbackGenericService* callback_generic_service, - int max_message_size = 0) { + bool SetUpServer(::grpc::Service* service1, ::grpc::Service* service2, + AsyncGenericService* generic_service, + CallbackGenericService* callback_generic_service, + int max_message_size = 0) { int port = grpc_pick_unused_port_or_die(); server_address_ << "localhost:" << port; @@ -268,8 +273,12 @@ class HybridEnd2endTest : public ::testing::TestWithParam { builder.RegisterAsyncGenericService(generic_service); } if (callback_generic_service) { +#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL + builder.RegisterCallbackGenericService(callback_generic_service); +#else builder.experimental().RegisterCallbackGenericService( callback_generic_service); +#endif } if (max_message_size != 0) { @@ -807,13 +816,13 @@ TEST_F(HybridEnd2endTest, GenericEcho) { TEST_P(HybridEnd2endTest, CallbackGenericEcho) { EchoTestService::WithGenericMethod_Echo service; - class GenericEchoService : public experimental::CallbackGenericService { + class GenericEchoService : public CallbackGenericService { private: - experimental::ServerGenericBidiReactor* CreateReactor( - experimental::GenericCallbackServerContext* context) override { + ServerGenericBidiReactor* CreateReactor( + GenericCallbackServerContext* context) override { EXPECT_EQ(context->method(), "/grpc.testing.EchoTestService/Echo"); - class Reactor : public experimental::ServerGenericBidiReactor { + class Reactor : public ServerGenericBidiReactor { public: Reactor() { StartRead(&request_); }