1 // 2 // 3 // Copyright 2016 gRPC authors. 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 // 17 // 18 19 #ifndef GRPCPP_IMPL_RPC_SERVICE_METHOD_H 20 #define GRPCPP_IMPL_RPC_SERVICE_METHOD_H 21 22 #include <grpcpp/impl/rpc_method.h> 23 #include <grpcpp/support/byte_buffer.h> 24 #include <grpcpp/support/config.h> 25 #include <grpcpp/support/status.h> 26 27 #include <climits> 28 #include <functional> 29 #include <map> 30 #include <memory> 31 #include <vector> 32 33 #include "absl/log/absl_check.h" 34 #include "absl/log/absl_log.h" 35 36 namespace grpc { 37 class ServerContextBase; 38 namespace internal { 39 /// Base class for running an RPC handler. 40 class MethodHandler { 41 public: ~MethodHandler()42 virtual ~MethodHandler() {} 43 struct HandlerParameter { 44 /// Constructor for HandlerParameter 45 /// 46 /// \param c : the gRPC Call structure for this server call 47 /// \param context : the ServerContext structure for this server call 48 /// \param req : the request payload, if appropriate for this RPC 49 /// \param req_status : the request status after any interceptors have run 50 /// \param handler_data: internal data for the handler. 51 /// \param requester : used only by the callback API. It is a function 52 /// called by the RPC Controller to request another RPC (and also 53 /// to set up the state required to make that request possible) HandlerParameterHandlerParameter54 HandlerParameter(Call* c, grpc::ServerContextBase* context, void* req, 55 Status req_status, void* handler_data, 56 std::function<void()> requester) 57 : call(c), 58 server_context(context), 59 request(req), 60 status(req_status), 61 internal_data(handler_data), 62 call_requester(std::move(requester)) {} ~HandlerParameterHandlerParameter63 ~HandlerParameter() {} 64 Call* const call; 65 grpc::ServerContextBase* const server_context; 66 void* const request; 67 const Status status; 68 void* const internal_data; 69 const std::function<void()> call_requester; 70 }; 71 virtual void RunHandler(const HandlerParameter& param) = 0; 72 73 // Returns a pointer to the deserialized request. \a status reflects the 74 // result of deserialization. This pointer and the status should be filled in 75 // a HandlerParameter and passed to RunHandler. It is illegal to access the 76 // pointer after calling RunHandler. Ownership of the deserialized request is 77 // retained by the handler. Returns nullptr if deserialization failed. Deserialize(grpc_call *,grpc_byte_buffer * req,Status *,void **)78 virtual void* Deserialize(grpc_call* /*call*/, grpc_byte_buffer* req, 79 Status* /*status*/, void** /*handler_data*/) { 80 ABSL_CHECK_EQ(req, nullptr); 81 return nullptr; 82 } 83 }; 84 85 /// Server side rpc method class 86 class RpcServiceMethod : public RpcMethod { 87 public: 88 /// Takes ownership of the handler RpcServiceMethod(const char * name,RpcMethod::RpcType type,MethodHandler * handler)89 RpcServiceMethod(const char* name, RpcMethod::RpcType type, 90 MethodHandler* handler) 91 : RpcMethod(name, type), 92 server_tag_(nullptr), 93 api_type_(ApiType::SYNC), 94 handler_(handler) {} 95 96 enum class ApiType { 97 SYNC, 98 ASYNC, 99 RAW, 100 CALL_BACK, // not CALLBACK because that is reserved in Windows 101 RAW_CALL_BACK, 102 }; 103 set_server_tag(void * tag)104 void set_server_tag(void* tag) { server_tag_ = tag; } server_tag()105 void* server_tag() const { return server_tag_; } 106 /// if MethodHandler is nullptr, then this is an async method handler()107 MethodHandler* handler() const { return handler_.get(); } api_type()108 ApiType api_type() const { return api_type_; } SetHandler(MethodHandler * handler)109 void SetHandler(MethodHandler* handler) { handler_.reset(handler); } SetServerApiType(RpcServiceMethod::ApiType type)110 void SetServerApiType(RpcServiceMethod::ApiType type) { 111 if ((api_type_ == ApiType::SYNC) && 112 (type == ApiType::ASYNC || type == ApiType::RAW)) { 113 // this marks this method as async 114 handler_.reset(); 115 } else if (api_type_ != ApiType::SYNC) { 116 // this is not an error condition, as it allows users to declare a server 117 // like WithRawMethod_foo<AsyncService>. However since it 118 // overwrites behavior, it should be logged. 119 ABSL_LOG(INFO) 120 << "You are marking method " << name() << " as '" 121 << TypeToString(api_type_) 122 << "', even though it was previously marked '" << TypeToString(type) 123 << "'. This behavior will overwrite the original behavior. If " 124 "you expected this then ignore this message."; 125 } 126 api_type_ = type; 127 } 128 129 private: 130 void* server_tag_; 131 ApiType api_type_; 132 std::unique_ptr<MethodHandler> handler_; 133 TypeToString(RpcServiceMethod::ApiType type)134 const char* TypeToString(RpcServiceMethod::ApiType type) { 135 switch (type) { 136 case ApiType::SYNC: 137 return "sync"; 138 case ApiType::ASYNC: 139 return "async"; 140 case ApiType::RAW: 141 return "raw"; 142 case ApiType::CALL_BACK: 143 return "callback"; 144 case ApiType::RAW_CALL_BACK: 145 return "raw_callback"; 146 default: 147 GPR_UNREACHABLE_CODE(return "unknown"); 148 } 149 } 150 }; 151 } // namespace internal 152 153 } // namespace grpc 154 155 #endif // GRPCPP_IMPL_RPC_SERVICE_METHOD_H 156