• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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