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_CODEGEN_RPC_SERVICE_METHOD_H 20 #define GRPCPP_IMPL_CODEGEN_RPC_SERVICE_METHOD_H 21 22 #include <climits> 23 #include <functional> 24 #include <map> 25 #include <memory> 26 #include <vector> 27 28 #include <grpc/impl/codegen/log.h> 29 #include <grpcpp/impl/codegen/byte_buffer.h> 30 #include <grpcpp/impl/codegen/config.h> 31 #include <grpcpp/impl/codegen/rpc_method.h> 32 #include <grpcpp/impl/codegen/status.h> 33 34 namespace grpc_impl { 35 class ServerContextBase; 36 } // namespace grpc_impl 37 38 namespace grpc { 39 namespace internal { 40 /// Base class for running an RPC handler. 41 class MethodHandler { 42 public: ~MethodHandler()43 virtual ~MethodHandler() {} 44 struct HandlerParameter { 45 /// Constructor for HandlerParameter 46 /// 47 /// \param c : the gRPC Call structure for this server call 48 /// \param context : the ServerContext structure for this server call 49 /// \param req : the request payload, if appropriate for this RPC 50 /// \param req_status : the request status after any interceptors have run 51 /// \param handler_data: internal data for the handler. 52 /// \param requester : used only by the callback API. It is a function 53 /// called by the RPC Controller to request another RPC (and also 54 /// to set up the state required to make that request possible) HandlerParameterHandlerParameter55 HandlerParameter(Call* c, ::grpc_impl::ServerContextBase* context, 56 void* req, Status req_status, void* handler_data, 57 std::function<void()> requester) 58 : call(c), 59 server_context(context), 60 request(req), 61 status(req_status), 62 internal_data(handler_data), 63 call_requester(std::move(requester)) {} ~HandlerParameterHandlerParameter64 ~HandlerParameter() {} 65 Call* const call; 66 ::grpc_impl::ServerContextBase* const server_context; 67 void* const request; 68 const Status status; 69 void* const internal_data; 70 const std::function<void()> call_requester; 71 }; 72 virtual void RunHandler(const HandlerParameter& param) = 0; 73 74 /* Returns a pointer to the deserialized request. \a status reflects the 75 result of deserialization. This pointer and the status should be filled in 76 a HandlerParameter and passed to RunHandler. It is illegal to access the 77 pointer after calling RunHandler. Ownership of the deserialized request is 78 retained by the handler. Returns nullptr if deserialization failed. */ Deserialize(grpc_call *,grpc_byte_buffer * req,Status *,void **)79 virtual void* Deserialize(grpc_call* /*call*/, grpc_byte_buffer* req, 80 Status* /*status*/, void** /*handler_data*/) { 81 GPR_CODEGEN_ASSERT(req == nullptr); 82 return nullptr; 83 } 84 }; 85 86 /// Server side rpc method class 87 class RpcServiceMethod : public RpcMethod { 88 public: 89 /// Takes ownership of the handler RpcServiceMethod(const char * name,RpcMethod::RpcType type,MethodHandler * handler)90 RpcServiceMethod(const char* name, RpcMethod::RpcType type, 91 MethodHandler* handler) 92 : RpcMethod(name, type), 93 server_tag_(nullptr), 94 api_type_(ApiType::SYNC), 95 handler_(handler) {} 96 97 enum class ApiType { 98 SYNC, 99 ASYNC, 100 RAW, 101 CALL_BACK, // not CALLBACK because that is reserved in Windows 102 RAW_CALL_BACK, 103 }; 104 set_server_tag(void * tag)105 void set_server_tag(void* tag) { server_tag_ = tag; } server_tag()106 void* server_tag() const { return server_tag_; } 107 /// if MethodHandler is nullptr, then this is an async method handler()108 MethodHandler* handler() const { return handler_.get(); } api_type()109 ApiType api_type() const { return api_type_; } SetHandler(MethodHandler * handler)110 void SetHandler(MethodHandler* handler) { handler_.reset(handler); } SetServerApiType(RpcServiceMethod::ApiType type)111 void SetServerApiType(RpcServiceMethod::ApiType type) { 112 if ((api_type_ == ApiType::SYNC) && 113 (type == ApiType::ASYNC || type == ApiType::RAW)) { 114 // this marks this method as async 115 handler_.reset(); 116 } else if (api_type_ != ApiType::SYNC) { 117 // this is not an error condition, as it allows users to declare a server 118 // like WithRawMethod_foo<AsyncService>. However since it 119 // overwrites behavior, it should be logged. 120 gpr_log( 121 GPR_INFO, 122 "You are marking method %s as '%s', even though it was " 123 "previously marked '%s'. This behavior will overwrite the original " 124 "behavior. If you expected this then ignore this message.", 125 name(), TypeToString(api_type_), TypeToString(type)); 126 } 127 api_type_ = type; 128 } 129 130 private: 131 void* server_tag_; 132 ApiType api_type_; 133 std::unique_ptr<MethodHandler> handler_; 134 TypeToString(RpcServiceMethod::ApiType type)135 const char* TypeToString(RpcServiceMethod::ApiType type) { 136 switch (type) { 137 case ApiType::SYNC: 138 return "sync"; 139 case ApiType::ASYNC: 140 return "async"; 141 case ApiType::RAW: 142 return "raw"; 143 case ApiType::CALL_BACK: 144 return "callback"; 145 case ApiType::RAW_CALL_BACK: 146 return "raw_callback"; 147 default: 148 GPR_UNREACHABLE_CODE(return "unknown"); 149 } 150 } 151 }; 152 } // namespace internal 153 154 } // namespace grpc 155 156 #endif // GRPCPP_IMPL_CODEGEN_RPC_SERVICE_METHOD_H 157