aboutsummaryrefslogtreecommitdiffhomepage
path: root/include/grpcpp/impl/codegen/rpc_service_method.h
blob: f465c5fc2f91f7f42332afbb42333c2439ae573c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/*
 *
 * Copyright 2016 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#ifndef GRPCPP_IMPL_CODEGEN_RPC_SERVICE_METHOD_H
#define GRPCPP_IMPL_CODEGEN_RPC_SERVICE_METHOD_H

#include <climits>
#include <functional>
#include <map>
#include <memory>
#include <vector>

#include <grpc/impl/codegen/log.h>
#include <grpcpp/impl/codegen/byte_buffer.h>
#include <grpcpp/impl/codegen/config.h>
#include <grpcpp/impl/codegen/rpc_method.h>
#include <grpcpp/impl/codegen/status.h>

namespace grpc {
class ServerContext;

namespace internal {
/// Base class for running an RPC handler.
class MethodHandler {
 public:
  virtual ~MethodHandler() {}
  struct HandlerParameter {
    /// Constructor for HandlerParameter
    ///
    /// \param c : the gRPC Call structure for this server call
    /// \param context : the ServerContext structure for this server call
    /// \param req : the request payload, if appropriate for this RPC
    /// \param req_status : the request status after any interceptors have run
    /// \param rpc_requester : used only by the callback API. It is a function
    ///        called by the RPC Controller to request another RPC (and also
    ///        to set up the state required to make that request possible)
    HandlerParameter(Call* c, ServerContext* context, void* req,
                     Status req_status, std::function<void()> requester)
        : call(c),
          server_context(context),
          request(req),
          status(req_status),
          call_requester(std::move(requester)) {}
    ~HandlerParameter() {}
    Call* call;
    ServerContext* server_context;
    void* request;
    Status status;
    std::function<void()> call_requester;
  };
  virtual void RunHandler(const HandlerParameter& param) = 0;

  /* Returns a pointer to the deserialized request. \a status reflects the
     result of deserialization. This pointer and the status should be filled in
     a HandlerParameter and passed to RunHandler. It is illegal to access the
     pointer after calling RunHandler. Ownership of the deserialized request is
     retained by the handler. Returns nullptr if deserialization failed. */
  virtual void* Deserialize(grpc_call* call, grpc_byte_buffer* req,
                            Status* status) {
    GPR_CODEGEN_ASSERT(req == nullptr);
    return nullptr;
  }
};

/// Server side rpc method class
class RpcServiceMethod : public RpcMethod {
 public:
  /// Takes ownership of the handler
  RpcServiceMethod(const char* name, RpcMethod::RpcType type,
                   MethodHandler* handler)
      : RpcMethod(name, type),
        server_tag_(nullptr),
        api_type_(ApiType::SYNC),
        handler_(handler) {}

  enum class ApiType {
    SYNC,
    ASYNC,
    RAW,
    CALL_BACK,  // not CALLBACK because that is reserved in Windows
    RAW_CALL_BACK,
  };

  void set_server_tag(void* tag) { server_tag_ = tag; }
  void* server_tag() const { return server_tag_; }
  /// if MethodHandler is nullptr, then this is an async method
  MethodHandler* handler() const { return handler_.get(); }
  ApiType api_type() const { return api_type_; }
  void SetHandler(MethodHandler* handler) { handler_.reset(handler); }
  void SetServerApiType(RpcServiceMethod::ApiType type) {
    if ((api_type_ == ApiType::SYNC) &&
        (type == ApiType::ASYNC || type == ApiType::RAW)) {
      // this marks this method as async
      handler_.reset();
    } else if (api_type_ != ApiType::SYNC) {
      // this is not an error condition, as it allows users to declare a server
      // like WithRawMethod_foo<AsyncService>. However since it
      // overwrites behavior, it should be logged.
      gpr_log(
          GPR_INFO,
          "You are marking method %s as '%s', even though it was "
          "previously marked '%s'. This behavior will overwrite the original "
          "behavior. If you expected this then ignore this message.",
          name(), TypeToString(api_type_), TypeToString(type));
    }
    api_type_ = type;
  }

 private:
  void* server_tag_;
  ApiType api_type_;
  std::unique_ptr<MethodHandler> handler_;

  const char* TypeToString(RpcServiceMethod::ApiType type) {
    switch (type) {
      case ApiType::SYNC:
        return "sync";
      case ApiType::ASYNC:
        return "async";
      case ApiType::RAW:
        return "raw";
      case ApiType::CALL_BACK:
        return "callback";
      case ApiType::RAW_CALL_BACK:
        return "raw_callback";
      default:
        GPR_UNREACHABLE_CODE(return "unknown");
    }
  }
};
}  // namespace internal

}  // namespace grpc

#endif  // GRPCPP_IMPL_CODEGEN_RPC_SERVICE_METHOD_H