| /* | |
| * | |
| * Copyright 2016 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_CODEGEN_RPC_SERVICE_METHOD_H | |
| #define GRPCPP_IMPL_CODEGEN_RPC_SERVICE_METHOD_H | |
| #include <climits> | |
| #include <functional> | |
| #include <map> | |
| #include <memory> | |
| #include <vector> | |
| #include <grpc/impl/codegen/log.h> | |
| #include <grpcpp/impl/codegen/byte_buffer.h> | |
| #include <grpcpp/impl/codegen/config.h> | |
| #include <grpcpp/impl/codegen/rpc_method.h> | |
| #include <grpcpp/impl/codegen/status.h> | |
| namespace grpc { | |
| class ServerContext; | |
| namespace internal { | |
| /// Base class for running an RPC handler. | |
| class MethodHandler { | |
| public: | |
| virtual ~MethodHandler() {} | |
| struct HandlerParameter { | |
| /// Constructor for HandlerParameter | |
| /// | |
| /// \param c : the gRPC Call structure for this server call | |
| /// \param context : the ServerContext structure for this server call | |
| /// \param req : the request payload, if appropriate for this RPC | |
| /// \param req_status : the request status after any interceptors have run | |
| /// \param rpc_requester : used only by the callback API. It is a function | |
| /// called by the RPC Controller to request another RPC (and also | |
| /// to set up the state required to make that request possible) | |
| HandlerParameter(Call* c, ServerContext* context, void* req, | |
| Status req_status, std::function<void()> requester) | |
| : call(c), | |
| server_context(context), | |
| request(req), | |
| status(req_status), | |
| call_requester(std::move(requester)) {} | |
| ~HandlerParameter() {} | |
| Call* call; | |
| ServerContext* server_context; | |
| void* request; | |
| Status status; | |
| std::function<void()> call_requester; | |
| }; | |
| virtual void RunHandler(const HandlerParameter& param) = 0; | |
| /* Returns a pointer to the deserialized request. \a status reflects the | |
| result of deserialization. This pointer and the status should be filled in | |
| a HandlerParameter and passed to RunHandler. It is illegal to access the | |
| pointer after calling RunHandler. Ownership of the deserialized request is | |
| retained by the handler. Returns nullptr if deserialization failed. */ | |
| virtual void* Deserialize(grpc_call* call, grpc_byte_buffer* req, | |
| Status* status) { | |
| GPR_CODEGEN_ASSERT(req == nullptr); | |
| return nullptr; | |
| } | |
| }; | |
| /// Server side rpc method class | |
| class RpcServiceMethod : public RpcMethod { | |
| public: | |
| /// Takes ownership of the handler | |
| RpcServiceMethod(const char* name, RpcMethod::RpcType type, | |
| MethodHandler* handler) | |
| : RpcMethod(name, type), | |
| server_tag_(nullptr), | |
| api_type_(ApiType::SYNC), | |
| handler_(handler) {} | |
| enum class ApiType { | |
| SYNC, | |
| ASYNC, | |
| RAW, | |
| CALL_BACK, // not CALLBACK because that is reserved in Windows | |
| RAW_CALL_BACK, | |
| }; | |
| void set_server_tag(void* tag) { server_tag_ = tag; } | |
| void* server_tag() const { return server_tag_; } | |
| /// if MethodHandler is nullptr, then this is an async method | |
| MethodHandler* handler() const { return handler_.get(); } | |
| ApiType api_type() const { return api_type_; } | |
| void SetHandler(MethodHandler* handler) { handler_.reset(handler); } | |
| void SetServerApiType(RpcServiceMethod::ApiType type) { | |
| if ((api_type_ == ApiType::SYNC) && | |
| (type == ApiType::ASYNC || type == ApiType::RAW)) { | |
| // this marks this method as async | |
| handler_.reset(); | |
| } else if (api_type_ != ApiType::SYNC) { | |
| // this is not an error condition, as it allows users to declare a server | |
| // like WithRawMethod_foo<AsyncService>. However since it | |
| // overwrites behavior, it should be logged. | |
| gpr_log( | |
| GPR_INFO, | |
| "You are marking method %s as '%s', even though it was " | |
| "previously marked '%s'. This behavior will overwrite the original " | |
| "behavior. If you expected this then ignore this message.", | |
| name(), TypeToString(api_type_), TypeToString(type)); | |
| } | |
| api_type_ = type; | |
| } | |
| private: | |
| void* server_tag_; | |
| ApiType api_type_; | |
| std::unique_ptr<MethodHandler> handler_; | |
| const char* TypeToString(RpcServiceMethod::ApiType type) { | |
| switch (type) { | |
| case ApiType::SYNC: | |
| return "sync"; | |
| case ApiType::ASYNC: | |
| return "async"; | |
| case ApiType::RAW: | |
| return "raw"; | |
| case ApiType::CALL_BACK: | |
| return "callback"; | |
| case ApiType::RAW_CALL_BACK: | |
| return "raw_callback"; | |
| default: | |
| GPR_UNREACHABLE_CODE(return "unknown"); | |
| } | |
| } | |
| }; | |
| } // namespace internal | |
| } // namespace grpc | |
| #endif // GRPCPP_IMPL_CODEGEN_RPC_SERVICE_METHOD_H |