• 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_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