| 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: |
| 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) |
| 55 | 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)) {} |
| 64 | ~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. */ |
| 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 |
| 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 | |
| 105 | void set_server_tag(void* tag) { server_tag_ = tag; } |
| 106 | void* server_tag() const { return server_tag_; } |
| 107 | /// if MethodHandler is nullptr, then this is an async method |
| 108 | MethodHandler* handler() const { return handler_.get(); } |
| 109 | ApiType api_type() const { return api_type_; } |
| 110 | void SetHandler(MethodHandler* handler) { handler_.reset(p: handler); } |
| 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 | format: "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(type: 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 | |
| 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 | |