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
34namespace grpc {
35class ServerContextBase;
36namespace internal {
37/// Base class for running an RPC handler.
38class MethodHandler {
39 public:
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)
52 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)) {}
61 ~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. */
76 virtual void* Deserialize(grpc_call* /*call*/, grpc_byte_buffer* req,
77 Status* /*status*/, void** /*handler_data*/) {
78 GPR_CODEGEN_ASSERT(req == nullptr);
79 return nullptr;
80 }
81};
82
83/// Server side rpc method class
84class RpcServiceMethod : public RpcMethod {
85 public:
86 /// Takes ownership of the 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
102 void set_server_tag(void* tag) { server_tag_ = tag; }
103 void* server_tag() const { return server_tag_; }
104 /// if MethodHandler is nullptr, then this is an async method
105 MethodHandler* handler() const { return handler_.get(); }
106 ApiType api_type() const { return api_type_; }
107 void SetHandler(MethodHandler* handler) { handler_.reset(p: handler); }
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 format: "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(type: 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
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

source code of include/grpcpp/impl/rpc_service_method.h