diff --git a/BUILD b/BUILD index e5083fb874d..797cc97adf6 100644 --- a/BUILD +++ b/BUILD @@ -346,6 +346,7 @@ GRPCXX_PUBLIC_HDRS = [ "include/grpcpp/impl/delegating_channel.h", "include/grpcpp/impl/grpc_library.h", "include/grpcpp/impl/intercepted_channel.h", + "include/grpcpp/impl/interceptor_common.h", "include/grpcpp/impl/metadata_map.h", "include/grpcpp/impl/method_handler_impl.h", "include/grpcpp/impl/rpc_method.h", diff --git a/CMakeLists.txt b/CMakeLists.txt index b904e0569bf..11f526fce58 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3450,6 +3450,7 @@ foreach(_hdr include/grpcpp/impl/delegating_channel.h include/grpcpp/impl/grpc_library.h include/grpcpp/impl/intercepted_channel.h + include/grpcpp/impl/interceptor_common.h include/grpcpp/impl/metadata_map.h include/grpcpp/impl/method_handler_impl.h include/grpcpp/impl/rpc_method.h @@ -4143,6 +4144,7 @@ foreach(_hdr include/grpcpp/impl/delegating_channel.h include/grpcpp/impl/grpc_library.h include/grpcpp/impl/intercepted_channel.h + include/grpcpp/impl/interceptor_common.h include/grpcpp/impl/metadata_map.h include/grpcpp/impl/method_handler_impl.h include/grpcpp/impl/rpc_method.h diff --git a/build_autogenerated.yaml b/build_autogenerated.yaml index bbadba3b2e8..0258a468bd3 100644 --- a/build_autogenerated.yaml +++ b/build_autogenerated.yaml @@ -2825,6 +2825,7 @@ libs: - include/grpcpp/impl/delegating_channel.h - include/grpcpp/impl/grpc_library.h - include/grpcpp/impl/intercepted_channel.h + - include/grpcpp/impl/interceptor_common.h - include/grpcpp/impl/metadata_map.h - include/grpcpp/impl/method_handler_impl.h - include/grpcpp/impl/rpc_method.h @@ -3249,6 +3250,7 @@ libs: - include/grpcpp/impl/delegating_channel.h - include/grpcpp/impl/grpc_library.h - include/grpcpp/impl/intercepted_channel.h + - include/grpcpp/impl/interceptor_common.h - include/grpcpp/impl/metadata_map.h - include/grpcpp/impl/method_handler_impl.h - include/grpcpp/impl/rpc_method.h diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index f5593353367..a8bb02af5ce 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -151,6 +151,7 @@ Pod::Spec.new do |s| 'include/grpcpp/impl/delegating_channel.h', 'include/grpcpp/impl/grpc_library.h', 'include/grpcpp/impl/intercepted_channel.h', + 'include/grpcpp/impl/interceptor_common.h', 'include/grpcpp/impl/metadata_map.h', 'include/grpcpp/impl/method_handler_impl.h', 'include/grpcpp/impl/rpc_method.h', diff --git a/include/grpcpp/impl/call_op_set.h b/include/grpcpp/impl/call_op_set.h index 2bfd659e689..8b5db9ddb21 100644 --- a/include/grpcpp/impl/call_op_set.h +++ b/include/grpcpp/impl/call_op_set.h @@ -33,8 +33,8 @@ #include #include #include -#include #include +#include #include #include #include diff --git a/include/grpcpp/impl/codegen/interceptor_common.h b/include/grpcpp/impl/codegen/interceptor_common.h index ddf36d7d43e..87aefd73c85 100644 --- a/include/grpcpp/impl/codegen/interceptor_common.h +++ b/include/grpcpp/impl/codegen/interceptor_common.h @@ -21,520 +21,7 @@ // IWYU pragma: private -#include -#include - -#include -#include -#include -#include -#include -#include - -namespace grpc { -namespace internal { - -class InterceptorBatchMethodsImpl - : public experimental::InterceptorBatchMethods { - public: - InterceptorBatchMethodsImpl() { - for (auto i = static_cast(0); - i < experimental::InterceptionHookPoints::NUM_INTERCEPTION_HOOKS; - i = static_cast( - static_cast(i) + 1)) { - hooks_[static_cast(i)] = false; - } - } - - ~InterceptorBatchMethodsImpl() override {} - - bool QueryInterceptionHookPoint( - experimental::InterceptionHookPoints type) override { - return hooks_[static_cast(type)]; - } - - void Proceed() override { - if (call_->client_rpc_info() != nullptr) { - return ProceedClient(); - } - GPR_CODEGEN_ASSERT(call_->server_rpc_info() != nullptr); - ProceedServer(); - } - - void Hijack() override { - // Only the client can hijack when sending down initial metadata - GPR_CODEGEN_ASSERT(!reverse_ && ops_ != nullptr && - call_->client_rpc_info() != nullptr); - // It is illegal to call Hijack twice - GPR_CODEGEN_ASSERT(!ran_hijacking_interceptor_); - auto* rpc_info = call_->client_rpc_info(); - rpc_info->hijacked_ = true; - rpc_info->hijacked_interceptor_ = current_interceptor_index_; - ClearHookPoints(); - ops_->SetHijackingState(); - ran_hijacking_interceptor_ = true; - rpc_info->RunInterceptor(this, current_interceptor_index_); - } - - void AddInterceptionHookPoint(experimental::InterceptionHookPoints type) { - hooks_[static_cast(type)] = true; - } - - ByteBuffer* GetSerializedSendMessage() override { - GPR_CODEGEN_ASSERT(orig_send_message_ != nullptr); - if (*orig_send_message_ != nullptr) { - GPR_CODEGEN_ASSERT(serializer_(*orig_send_message_).ok()); - *orig_send_message_ = nullptr; - } - return send_message_; - } - - const void* GetSendMessage() override { - GPR_CODEGEN_ASSERT(orig_send_message_ != nullptr); - return *orig_send_message_; - } - - void ModifySendMessage(const void* message) override { - GPR_CODEGEN_ASSERT(orig_send_message_ != nullptr); - *orig_send_message_ = message; - } - - bool GetSendMessageStatus() override { return !*fail_send_message_; } - - std::multimap* GetSendInitialMetadata() override { - return send_initial_metadata_; - } - - Status GetSendStatus() override { - return Status(static_cast(*code_), *error_message_, - *error_details_); - } - - void ModifySendStatus(const Status& status) override { - *code_ = static_cast(status.error_code()); - *error_details_ = status.error_details(); - *error_message_ = status.error_message(); - } - - std::multimap* GetSendTrailingMetadata() override { - return send_trailing_metadata_; - } - - void* GetRecvMessage() override { return recv_message_; } - - std::multimap* GetRecvInitialMetadata() - override { - return recv_initial_metadata_->map(); - } - - Status* GetRecvStatus() override { return recv_status_; } - - void FailHijackedSendMessage() override { - GPR_CODEGEN_ASSERT(hooks_[static_cast( - experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)]); - *fail_send_message_ = true; - } - - std::multimap* GetRecvTrailingMetadata() - override { - return recv_trailing_metadata_->map(); - } - - void SetSendMessage(ByteBuffer* buf, const void** msg, - bool* fail_send_message, - std::function serializer) { - send_message_ = buf; - orig_send_message_ = msg; - fail_send_message_ = fail_send_message; - serializer_ = serializer; - } - - void SetSendInitialMetadata( - std::multimap* metadata) { - send_initial_metadata_ = metadata; - } - - void SetSendStatus(grpc_status_code* code, std::string* error_details, - std::string* error_message) { - code_ = code; - error_details_ = error_details; - error_message_ = error_message; - } - - void SetSendTrailingMetadata( - std::multimap* metadata) { - send_trailing_metadata_ = metadata; - } - - void SetRecvMessage(void* message, bool* hijacked_recv_message_failed) { - recv_message_ = message; - hijacked_recv_message_failed_ = hijacked_recv_message_failed; - } - - void SetRecvInitialMetadata(MetadataMap* map) { - recv_initial_metadata_ = map; - } - - void SetRecvStatus(Status* status) { recv_status_ = status; } - - void SetRecvTrailingMetadata(MetadataMap* map) { - recv_trailing_metadata_ = map; - } - - std::unique_ptr GetInterceptedChannel() override { - auto* info = call_->client_rpc_info(); - if (info == nullptr) { - return std::unique_ptr(nullptr); - } - // The intercepted channel starts from the interceptor just after the - // current interceptor - return std::unique_ptr(new InterceptedChannel( - info->channel(), current_interceptor_index_ + 1)); - } - - void FailHijackedRecvMessage() override { - GPR_CODEGEN_ASSERT(hooks_[static_cast( - experimental::InterceptionHookPoints::PRE_RECV_MESSAGE)]); - *hijacked_recv_message_failed_ = true; - } - - // Clears all state - void ClearState() { - reverse_ = false; - ran_hijacking_interceptor_ = false; - ClearHookPoints(); - } - - // Prepares for Post_recv operations - void SetReverse() { - reverse_ = true; - ran_hijacking_interceptor_ = false; - ClearHookPoints(); - } - - // This needs to be set before interceptors are run - void SetCall(Call* call) { call_ = call; } - - // This needs to be set before interceptors are run using RunInterceptors(). - // Alternatively, RunInterceptors(std::function f) can be used. - void SetCallOpSetInterface(CallOpSetInterface* ops) { ops_ = ops; } - - // SetCall should have been called before this. - // Returns true if the interceptors list is empty - bool InterceptorsListEmpty() { - auto* client_rpc_info = call_->client_rpc_info(); - if (client_rpc_info != nullptr) { - return client_rpc_info->interceptors_.empty(); - } - - auto* server_rpc_info = call_->server_rpc_info(); - return server_rpc_info == nullptr || server_rpc_info->interceptors_.empty(); - } - - // This should be used only by subclasses of CallOpSetInterface. SetCall and - // SetCallOpSetInterface should have been called before this. After all the - // interceptors are done running, either ContinueFillOpsAfterInterception or - // ContinueFinalizeOpsAfterInterception will be called. Note that neither of - // them is invoked if there were no interceptors registered. - bool RunInterceptors() { - GPR_CODEGEN_ASSERT(ops_); - auto* client_rpc_info = call_->client_rpc_info(); - if (client_rpc_info != nullptr) { - if (client_rpc_info->interceptors_.empty()) { - return true; - } else { - RunClientInterceptors(); - return false; - } - } - - auto* server_rpc_info = call_->server_rpc_info(); - if (server_rpc_info == nullptr || server_rpc_info->interceptors_.empty()) { - return true; - } - RunServerInterceptors(); - return false; - } - - // Returns true if no interceptors are run. Returns false otherwise if there - // are interceptors registered. After the interceptors are done running \a f - // will be invoked. This is to be used only by BaseAsyncRequest and - // SyncRequest. - bool RunInterceptors(std::function f) { - // This is used only by the server for initial call request - GPR_CODEGEN_ASSERT(reverse_ == true); - GPR_CODEGEN_ASSERT(call_->client_rpc_info() == nullptr); - auto* server_rpc_info = call_->server_rpc_info(); - if (server_rpc_info == nullptr || server_rpc_info->interceptors_.empty()) { - return true; - } - callback_ = std::move(f); - RunServerInterceptors(); - return false; - } - - private: - void RunClientInterceptors() { - auto* rpc_info = call_->client_rpc_info(); - if (!reverse_) { - current_interceptor_index_ = 0; - } else { - if (rpc_info->hijacked_) { - current_interceptor_index_ = rpc_info->hijacked_interceptor_; - } else { - current_interceptor_index_ = rpc_info->interceptors_.size() - 1; - } - } - rpc_info->RunInterceptor(this, current_interceptor_index_); - } - - void RunServerInterceptors() { - auto* rpc_info = call_->server_rpc_info(); - if (!reverse_) { - current_interceptor_index_ = 0; - } else { - current_interceptor_index_ = rpc_info->interceptors_.size() - 1; - } - rpc_info->RunInterceptor(this, current_interceptor_index_); - } - - void ProceedClient() { - auto* rpc_info = call_->client_rpc_info(); - if (rpc_info->hijacked_ && !reverse_ && - current_interceptor_index_ == rpc_info->hijacked_interceptor_ && - !ran_hijacking_interceptor_) { - // We now need to provide hijacked recv ops to this interceptor - ClearHookPoints(); - ops_->SetHijackingState(); - ran_hijacking_interceptor_ = true; - rpc_info->RunInterceptor(this, current_interceptor_index_); - return; - } - if (!reverse_) { - current_interceptor_index_++; - // We are going down the stack of interceptors - if (current_interceptor_index_ < rpc_info->interceptors_.size()) { - if (rpc_info->hijacked_ && - current_interceptor_index_ > rpc_info->hijacked_interceptor_) { - // This is a hijacked RPC and we are done with hijacking - ops_->ContinueFillOpsAfterInterception(); - } else { - rpc_info->RunInterceptor(this, current_interceptor_index_); - } - } else { - // we are done running all the interceptors without any hijacking - ops_->ContinueFillOpsAfterInterception(); - } - } else { - // We are going up the stack of interceptors - if (current_interceptor_index_ > 0) { - // Continue running interceptors - current_interceptor_index_--; - rpc_info->RunInterceptor(this, current_interceptor_index_); - } else { - // we are done running all the interceptors without any hijacking - ops_->ContinueFinalizeResultAfterInterception(); - } - } - } - - void ProceedServer() { - auto* rpc_info = call_->server_rpc_info(); - if (!reverse_) { - current_interceptor_index_++; - if (current_interceptor_index_ < rpc_info->interceptors_.size()) { - return rpc_info->RunInterceptor(this, current_interceptor_index_); - } else if (ops_) { - return ops_->ContinueFillOpsAfterInterception(); - } - } else { - // We are going up the stack of interceptors - if (current_interceptor_index_ > 0) { - // Continue running interceptors - current_interceptor_index_--; - return rpc_info->RunInterceptor(this, current_interceptor_index_); - } else if (ops_) { - return ops_->ContinueFinalizeResultAfterInterception(); - } - } - GPR_CODEGEN_ASSERT(callback_); - callback_(); - } - - void ClearHookPoints() { - for (auto i = static_cast(0); - i < experimental::InterceptionHookPoints::NUM_INTERCEPTION_HOOKS; - i = static_cast( - static_cast(i) + 1)) { - hooks_[static_cast(i)] = false; - } - } - - std::array( - experimental::InterceptionHookPoints::NUM_INTERCEPTION_HOOKS)> - hooks_; - - size_t current_interceptor_index_ = 0; // Current iterator - bool reverse_ = false; - bool ran_hijacking_interceptor_ = false; - Call* call_ = nullptr; // The Call object is present along with CallOpSet - // object/callback - CallOpSetInterface* ops_ = nullptr; - std::function callback_; - - ByteBuffer* send_message_ = nullptr; - bool* fail_send_message_ = nullptr; - const void** orig_send_message_ = nullptr; - std::function serializer_; - - std::multimap* send_initial_metadata_; - - grpc_status_code* code_ = nullptr; - std::string* error_details_ = nullptr; - std::string* error_message_ = nullptr; - - std::multimap* send_trailing_metadata_ = nullptr; - - void* recv_message_ = nullptr; - bool* hijacked_recv_message_failed_ = nullptr; - - MetadataMap* recv_initial_metadata_ = nullptr; - - Status* recv_status_ = nullptr; - - MetadataMap* recv_trailing_metadata_ = nullptr; -}; - -// A special implementation of InterceptorBatchMethods to send a Cancel -// notification down the interceptor stack -class CancelInterceptorBatchMethods - : public experimental::InterceptorBatchMethods { - public: - bool QueryInterceptionHookPoint( - experimental::InterceptionHookPoints type) override { - return type == experimental::InterceptionHookPoints::PRE_SEND_CANCEL; - } - - void Proceed() override { - // This is a no-op. For actual continuation of the RPC simply needs to - // return from the Intercept method - } - - void Hijack() override { - // Only the client can hijack when sending down initial metadata - GPR_CODEGEN_ASSERT(false && - "It is illegal to call Hijack on a method which has a " - "Cancel notification"); - } - - ByteBuffer* GetSerializedSendMessage() override { - GPR_CODEGEN_ASSERT(false && - "It is illegal to call GetSendMessage on a method which " - "has a Cancel notification"); - return nullptr; - } - - bool GetSendMessageStatus() override { - GPR_CODEGEN_ASSERT( - false && - "It is illegal to call GetSendMessageStatus on a method which " - "has a Cancel notification"); - return false; - } - - const void* GetSendMessage() override { - GPR_CODEGEN_ASSERT( - false && - "It is illegal to call GetOriginalSendMessage on a method which " - "has a Cancel notification"); - return nullptr; - } - - void ModifySendMessage(const void* /*message*/) override { - GPR_CODEGEN_ASSERT( - false && - "It is illegal to call ModifySendMessage on a method which " - "has a Cancel notification"); - } - - std::multimap* GetSendInitialMetadata() override { - GPR_CODEGEN_ASSERT(false && - "It is illegal to call GetSendInitialMetadata on a " - "method which has a Cancel notification"); - return nullptr; - } - - Status GetSendStatus() override { - GPR_CODEGEN_ASSERT(false && - "It is illegal to call GetSendStatus on a method which " - "has a Cancel notification"); - return Status(); - } - - void ModifySendStatus(const Status& /*status*/) override { - GPR_CODEGEN_ASSERT(false && - "It is illegal to call ModifySendStatus on a method " - "which has a Cancel notification"); - } - - std::multimap* GetSendTrailingMetadata() override { - GPR_CODEGEN_ASSERT(false && - "It is illegal to call GetSendTrailingMetadata on a " - "method which has a Cancel notification"); - return nullptr; - } - - void* GetRecvMessage() override { - GPR_CODEGEN_ASSERT(false && - "It is illegal to call GetRecvMessage on a method which " - "has a Cancel notification"); - return nullptr; - } - - std::multimap* GetRecvInitialMetadata() - override { - GPR_CODEGEN_ASSERT(false && - "It is illegal to call GetRecvInitialMetadata on a " - "method which has a Cancel notification"); - return nullptr; - } - - Status* GetRecvStatus() override { - GPR_CODEGEN_ASSERT(false && - "It is illegal to call GetRecvStatus on a method which " - "has a Cancel notification"); - return nullptr; - } - - std::multimap* GetRecvTrailingMetadata() - override { - GPR_CODEGEN_ASSERT(false && - "It is illegal to call GetRecvTrailingMetadata on a " - "method which has a Cancel notification"); - return nullptr; - } - - std::unique_ptr GetInterceptedChannel() override { - GPR_CODEGEN_ASSERT(false && - "It is illegal to call GetInterceptedChannel on a " - "method which has a Cancel notification"); - return std::unique_ptr(nullptr); - } - - void FailHijackedRecvMessage() override { - GPR_CODEGEN_ASSERT(false && - "It is illegal to call FailHijackedRecvMessage on a " - "method which has a Cancel notification"); - } - - void FailHijackedSendMessage() override { - GPR_CODEGEN_ASSERT(false && - "It is illegal to call FailHijackedSendMessage on a " - "method which has a Cancel notification"); - } -}; -} // namespace internal -} // namespace grpc +/// TODO(chengyuc): Remove this file after solving compatibility. +#include #endif // GRPCPP_IMPL_CODEGEN_INTERCEPTOR_COMMON_H diff --git a/include/grpcpp/impl/interceptor_common.h b/include/grpcpp/impl/interceptor_common.h new file mode 100644 index 00000000000..8f6d4e16f4e --- /dev/null +++ b/include/grpcpp/impl/interceptor_common.h @@ -0,0 +1,538 @@ +/* + * + * Copyright 2018 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#ifndef GRPCPP_IMPL_INTERCEPTOR_COMMON_H +#define GRPCPP_IMPL_INTERCEPTOR_COMMON_H + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace grpc { +namespace internal { + +class InterceptorBatchMethodsImpl + : public experimental::InterceptorBatchMethods { + public: + InterceptorBatchMethodsImpl() { + for (auto i = static_cast(0); + i < experimental::InterceptionHookPoints::NUM_INTERCEPTION_HOOKS; + i = static_cast( + static_cast(i) + 1)) { + hooks_[static_cast(i)] = false; + } + } + + ~InterceptorBatchMethodsImpl() override {} + + bool QueryInterceptionHookPoint( + experimental::InterceptionHookPoints type) override { + return hooks_[static_cast(type)]; + } + + void Proceed() override { + if (call_->client_rpc_info() != nullptr) { + return ProceedClient(); + } + GPR_CODEGEN_ASSERT(call_->server_rpc_info() != nullptr); + ProceedServer(); + } + + void Hijack() override { + // Only the client can hijack when sending down initial metadata + GPR_CODEGEN_ASSERT(!reverse_ && ops_ != nullptr && + call_->client_rpc_info() != nullptr); + // It is illegal to call Hijack twice + GPR_CODEGEN_ASSERT(!ran_hijacking_interceptor_); + auto* rpc_info = call_->client_rpc_info(); + rpc_info->hijacked_ = true; + rpc_info->hijacked_interceptor_ = current_interceptor_index_; + ClearHookPoints(); + ops_->SetHijackingState(); + ran_hijacking_interceptor_ = true; + rpc_info->RunInterceptor(this, current_interceptor_index_); + } + + void AddInterceptionHookPoint(experimental::InterceptionHookPoints type) { + hooks_[static_cast(type)] = true; + } + + ByteBuffer* GetSerializedSendMessage() override { + GPR_CODEGEN_ASSERT(orig_send_message_ != nullptr); + if (*orig_send_message_ != nullptr) { + GPR_CODEGEN_ASSERT(serializer_(*orig_send_message_).ok()); + *orig_send_message_ = nullptr; + } + return send_message_; + } + + const void* GetSendMessage() override { + GPR_CODEGEN_ASSERT(orig_send_message_ != nullptr); + return *orig_send_message_; + } + + void ModifySendMessage(const void* message) override { + GPR_CODEGEN_ASSERT(orig_send_message_ != nullptr); + *orig_send_message_ = message; + } + + bool GetSendMessageStatus() override { return !*fail_send_message_; } + + std::multimap* GetSendInitialMetadata() override { + return send_initial_metadata_; + } + + Status GetSendStatus() override { + return Status(static_cast(*code_), *error_message_, + *error_details_); + } + + void ModifySendStatus(const Status& status) override { + *code_ = static_cast(status.error_code()); + *error_details_ = status.error_details(); + *error_message_ = status.error_message(); + } + + std::multimap* GetSendTrailingMetadata() override { + return send_trailing_metadata_; + } + + void* GetRecvMessage() override { return recv_message_; } + + std::multimap* GetRecvInitialMetadata() + override { + return recv_initial_metadata_->map(); + } + + Status* GetRecvStatus() override { return recv_status_; } + + void FailHijackedSendMessage() override { + GPR_CODEGEN_ASSERT(hooks_[static_cast( + experimental::InterceptionHookPoints::PRE_SEND_MESSAGE)]); + *fail_send_message_ = true; + } + + std::multimap* GetRecvTrailingMetadata() + override { + return recv_trailing_metadata_->map(); + } + + void SetSendMessage(ByteBuffer* buf, const void** msg, + bool* fail_send_message, + std::function serializer) { + send_message_ = buf; + orig_send_message_ = msg; + fail_send_message_ = fail_send_message; + serializer_ = serializer; + } + + void SetSendInitialMetadata( + std::multimap* metadata) { + send_initial_metadata_ = metadata; + } + + void SetSendStatus(grpc_status_code* code, std::string* error_details, + std::string* error_message) { + code_ = code; + error_details_ = error_details; + error_message_ = error_message; + } + + void SetSendTrailingMetadata( + std::multimap* metadata) { + send_trailing_metadata_ = metadata; + } + + void SetRecvMessage(void* message, bool* hijacked_recv_message_failed) { + recv_message_ = message; + hijacked_recv_message_failed_ = hijacked_recv_message_failed; + } + + void SetRecvInitialMetadata(MetadataMap* map) { + recv_initial_metadata_ = map; + } + + void SetRecvStatus(Status* status) { recv_status_ = status; } + + void SetRecvTrailingMetadata(MetadataMap* map) { + recv_trailing_metadata_ = map; + } + + std::unique_ptr GetInterceptedChannel() override { + auto* info = call_->client_rpc_info(); + if (info == nullptr) { + return std::unique_ptr(nullptr); + } + // The intercepted channel starts from the interceptor just after the + // current interceptor + return std::unique_ptr(new InterceptedChannel( + info->channel(), current_interceptor_index_ + 1)); + } + + void FailHijackedRecvMessage() override { + GPR_CODEGEN_ASSERT(hooks_[static_cast( + experimental::InterceptionHookPoints::PRE_RECV_MESSAGE)]); + *hijacked_recv_message_failed_ = true; + } + + // Clears all state + void ClearState() { + reverse_ = false; + ran_hijacking_interceptor_ = false; + ClearHookPoints(); + } + + // Prepares for Post_recv operations + void SetReverse() { + reverse_ = true; + ran_hijacking_interceptor_ = false; + ClearHookPoints(); + } + + // This needs to be set before interceptors are run + void SetCall(Call* call) { call_ = call; } + + // This needs to be set before interceptors are run using RunInterceptors(). + // Alternatively, RunInterceptors(std::function f) can be used. + void SetCallOpSetInterface(CallOpSetInterface* ops) { ops_ = ops; } + + // SetCall should have been called before this. + // Returns true if the interceptors list is empty + bool InterceptorsListEmpty() { + auto* client_rpc_info = call_->client_rpc_info(); + if (client_rpc_info != nullptr) { + return client_rpc_info->interceptors_.empty(); + } + + auto* server_rpc_info = call_->server_rpc_info(); + return server_rpc_info == nullptr || server_rpc_info->interceptors_.empty(); + } + + // This should be used only by subclasses of CallOpSetInterface. SetCall and + // SetCallOpSetInterface should have been called before this. After all the + // interceptors are done running, either ContinueFillOpsAfterInterception or + // ContinueFinalizeOpsAfterInterception will be called. Note that neither of + // them is invoked if there were no interceptors registered. + bool RunInterceptors() { + GPR_CODEGEN_ASSERT(ops_); + auto* client_rpc_info = call_->client_rpc_info(); + if (client_rpc_info != nullptr) { + if (client_rpc_info->interceptors_.empty()) { + return true; + } else { + RunClientInterceptors(); + return false; + } + } + + auto* server_rpc_info = call_->server_rpc_info(); + if (server_rpc_info == nullptr || server_rpc_info->interceptors_.empty()) { + return true; + } + RunServerInterceptors(); + return false; + } + + // Returns true if no interceptors are run. Returns false otherwise if there + // are interceptors registered. After the interceptors are done running \a f + // will be invoked. This is to be used only by BaseAsyncRequest and + // SyncRequest. + bool RunInterceptors(std::function f) { + // This is used only by the server for initial call request + GPR_CODEGEN_ASSERT(reverse_ == true); + GPR_CODEGEN_ASSERT(call_->client_rpc_info() == nullptr); + auto* server_rpc_info = call_->server_rpc_info(); + if (server_rpc_info == nullptr || server_rpc_info->interceptors_.empty()) { + return true; + } + callback_ = std::move(f); + RunServerInterceptors(); + return false; + } + + private: + void RunClientInterceptors() { + auto* rpc_info = call_->client_rpc_info(); + if (!reverse_) { + current_interceptor_index_ = 0; + } else { + if (rpc_info->hijacked_) { + current_interceptor_index_ = rpc_info->hijacked_interceptor_; + } else { + current_interceptor_index_ = rpc_info->interceptors_.size() - 1; + } + } + rpc_info->RunInterceptor(this, current_interceptor_index_); + } + + void RunServerInterceptors() { + auto* rpc_info = call_->server_rpc_info(); + if (!reverse_) { + current_interceptor_index_ = 0; + } else { + current_interceptor_index_ = rpc_info->interceptors_.size() - 1; + } + rpc_info->RunInterceptor(this, current_interceptor_index_); + } + + void ProceedClient() { + auto* rpc_info = call_->client_rpc_info(); + if (rpc_info->hijacked_ && !reverse_ && + current_interceptor_index_ == rpc_info->hijacked_interceptor_ && + !ran_hijacking_interceptor_) { + // We now need to provide hijacked recv ops to this interceptor + ClearHookPoints(); + ops_->SetHijackingState(); + ran_hijacking_interceptor_ = true; + rpc_info->RunInterceptor(this, current_interceptor_index_); + return; + } + if (!reverse_) { + current_interceptor_index_++; + // We are going down the stack of interceptors + if (current_interceptor_index_ < rpc_info->interceptors_.size()) { + if (rpc_info->hijacked_ && + current_interceptor_index_ > rpc_info->hijacked_interceptor_) { + // This is a hijacked RPC and we are done with hijacking + ops_->ContinueFillOpsAfterInterception(); + } else { + rpc_info->RunInterceptor(this, current_interceptor_index_); + } + } else { + // we are done running all the interceptors without any hijacking + ops_->ContinueFillOpsAfterInterception(); + } + } else { + // We are going up the stack of interceptors + if (current_interceptor_index_ > 0) { + // Continue running interceptors + current_interceptor_index_--; + rpc_info->RunInterceptor(this, current_interceptor_index_); + } else { + // we are done running all the interceptors without any hijacking + ops_->ContinueFinalizeResultAfterInterception(); + } + } + } + + void ProceedServer() { + auto* rpc_info = call_->server_rpc_info(); + if (!reverse_) { + current_interceptor_index_++; + if (current_interceptor_index_ < rpc_info->interceptors_.size()) { + return rpc_info->RunInterceptor(this, current_interceptor_index_); + } else if (ops_) { + return ops_->ContinueFillOpsAfterInterception(); + } + } else { + // We are going up the stack of interceptors + if (current_interceptor_index_ > 0) { + // Continue running interceptors + current_interceptor_index_--; + return rpc_info->RunInterceptor(this, current_interceptor_index_); + } else if (ops_) { + return ops_->ContinueFinalizeResultAfterInterception(); + } + } + GPR_CODEGEN_ASSERT(callback_); + callback_(); + } + + void ClearHookPoints() { + for (auto i = static_cast(0); + i < experimental::InterceptionHookPoints::NUM_INTERCEPTION_HOOKS; + i = static_cast( + static_cast(i) + 1)) { + hooks_[static_cast(i)] = false; + } + } + + std::array( + experimental::InterceptionHookPoints::NUM_INTERCEPTION_HOOKS)> + hooks_; + + size_t current_interceptor_index_ = 0; // Current iterator + bool reverse_ = false; + bool ran_hijacking_interceptor_ = false; + Call* call_ = nullptr; // The Call object is present along with CallOpSet + // object/callback + CallOpSetInterface* ops_ = nullptr; + std::function callback_; + + ByteBuffer* send_message_ = nullptr; + bool* fail_send_message_ = nullptr; + const void** orig_send_message_ = nullptr; + std::function serializer_; + + std::multimap* send_initial_metadata_; + + grpc_status_code* code_ = nullptr; + std::string* error_details_ = nullptr; + std::string* error_message_ = nullptr; + + std::multimap* send_trailing_metadata_ = nullptr; + + void* recv_message_ = nullptr; + bool* hijacked_recv_message_failed_ = nullptr; + + MetadataMap* recv_initial_metadata_ = nullptr; + + Status* recv_status_ = nullptr; + + MetadataMap* recv_trailing_metadata_ = nullptr; +}; + +// A special implementation of InterceptorBatchMethods to send a Cancel +// notification down the interceptor stack +class CancelInterceptorBatchMethods + : public experimental::InterceptorBatchMethods { + public: + bool QueryInterceptionHookPoint( + experimental::InterceptionHookPoints type) override { + return type == experimental::InterceptionHookPoints::PRE_SEND_CANCEL; + } + + void Proceed() override { + // This is a no-op. For actual continuation of the RPC simply needs to + // return from the Intercept method + } + + void Hijack() override { + // Only the client can hijack when sending down initial metadata + GPR_CODEGEN_ASSERT(false && + "It is illegal to call Hijack on a method which has a " + "Cancel notification"); + } + + ByteBuffer* GetSerializedSendMessage() override { + GPR_CODEGEN_ASSERT(false && + "It is illegal to call GetSendMessage on a method which " + "has a Cancel notification"); + return nullptr; + } + + bool GetSendMessageStatus() override { + GPR_CODEGEN_ASSERT( + false && + "It is illegal to call GetSendMessageStatus on a method which " + "has a Cancel notification"); + return false; + } + + const void* GetSendMessage() override { + GPR_CODEGEN_ASSERT( + false && + "It is illegal to call GetOriginalSendMessage on a method which " + "has a Cancel notification"); + return nullptr; + } + + void ModifySendMessage(const void* /*message*/) override { + GPR_CODEGEN_ASSERT( + false && + "It is illegal to call ModifySendMessage on a method which " + "has a Cancel notification"); + } + + std::multimap* GetSendInitialMetadata() override { + GPR_CODEGEN_ASSERT(false && + "It is illegal to call GetSendInitialMetadata on a " + "method which has a Cancel notification"); + return nullptr; + } + + Status GetSendStatus() override { + GPR_CODEGEN_ASSERT(false && + "It is illegal to call GetSendStatus on a method which " + "has a Cancel notification"); + return Status(); + } + + void ModifySendStatus(const Status& /*status*/) override { + GPR_CODEGEN_ASSERT(false && + "It is illegal to call ModifySendStatus on a method " + "which has a Cancel notification"); + } + + std::multimap* GetSendTrailingMetadata() override { + GPR_CODEGEN_ASSERT(false && + "It is illegal to call GetSendTrailingMetadata on a " + "method which has a Cancel notification"); + return nullptr; + } + + void* GetRecvMessage() override { + GPR_CODEGEN_ASSERT(false && + "It is illegal to call GetRecvMessage on a method which " + "has a Cancel notification"); + return nullptr; + } + + std::multimap* GetRecvInitialMetadata() + override { + GPR_CODEGEN_ASSERT(false && + "It is illegal to call GetRecvInitialMetadata on a " + "method which has a Cancel notification"); + return nullptr; + } + + Status* GetRecvStatus() override { + GPR_CODEGEN_ASSERT(false && + "It is illegal to call GetRecvStatus on a method which " + "has a Cancel notification"); + return nullptr; + } + + std::multimap* GetRecvTrailingMetadata() + override { + GPR_CODEGEN_ASSERT(false && + "It is illegal to call GetRecvTrailingMetadata on a " + "method which has a Cancel notification"); + return nullptr; + } + + std::unique_ptr GetInterceptedChannel() override { + GPR_CODEGEN_ASSERT(false && + "It is illegal to call GetInterceptedChannel on a " + "method which has a Cancel notification"); + return std::unique_ptr(nullptr); + } + + void FailHijackedRecvMessage() override { + GPR_CODEGEN_ASSERT(false && + "It is illegal to call FailHijackedRecvMessage on a " + "method which has a Cancel notification"); + } + + void FailHijackedSendMessage() override { + GPR_CODEGEN_ASSERT(false && + "It is illegal to call FailHijackedSendMessage on a " + "method which has a Cancel notification"); + } +}; +} // namespace internal +} // namespace grpc + +#endif // GRPCPP_IMPL_INTERCEPTOR_COMMON_H diff --git a/src/cpp/client/client_context.cc b/src/cpp/client/client_context.cc index e58ebcbfbe3..e536f4b547b 100644 --- a/src/cpp/client/client_context.cc +++ b/src/cpp/client/client_context.cc @@ -35,9 +35,9 @@ #include #include #include -#include #include #include +#include #include #include #include diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index 81edc9fb9db..3931bcd14b5 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -45,10 +45,10 @@ #include #include #include -#include #include #include #include +#include #include #include #include diff --git a/src/cpp/server/server_context.cc b/src/cpp/server/server_context.cc index 2954053d36a..ca52c8e2c97 100644 --- a/src/cpp/server/server_context.cc +++ b/src/cpp/server/server_context.cc @@ -44,9 +44,9 @@ #include #include #include -#include #include #include +#include #include #include #include diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++ index 3609a72fc68..2ddc0b4088c 100644 --- a/tools/doxygen/Doxyfile.c++ +++ b/tools/doxygen/Doxyfile.c++ @@ -1015,6 +1015,7 @@ include/grpcpp/impl/create_auth_context.h \ include/grpcpp/impl/delegating_channel.h \ include/grpcpp/impl/grpc_library.h \ include/grpcpp/impl/intercepted_channel.h \ +include/grpcpp/impl/interceptor_common.h \ include/grpcpp/impl/metadata_map.h \ include/grpcpp/impl/method_handler_impl.h \ include/grpcpp/impl/rpc_method.h \ diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal index 0ec213d2dab..b5c3d5193fe 100644 --- a/tools/doxygen/Doxyfile.c++.internal +++ b/tools/doxygen/Doxyfile.c++.internal @@ -1015,6 +1015,7 @@ include/grpcpp/impl/create_auth_context.h \ include/grpcpp/impl/delegating_channel.h \ include/grpcpp/impl/grpc_library.h \ include/grpcpp/impl/intercepted_channel.h \ +include/grpcpp/impl/interceptor_common.h \ include/grpcpp/impl/metadata_map.h \ include/grpcpp/impl/method_handler_impl.h \ include/grpcpp/impl/rpc_method.h \