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