Imported Upstream version 1.41.0
[platform/upstream/grpc.git] / include / grpcpp / impl / codegen / service_type.h
1 /*
2  *
3  * Copyright 2015 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_SERVICE_TYPE_H
20 #define GRPCPP_IMPL_CODEGEN_SERVICE_TYPE_H
21
22 // IWYU pragma: private, include <grpcpp/impl/service_type.h>
23
24 #include <grpcpp/impl/codegen/config.h>
25 #include <grpcpp/impl/codegen/core_codegen_interface.h>
26 #include <grpcpp/impl/codegen/rpc_service_method.h>
27 #include <grpcpp/impl/codegen/serialization_traits.h>
28 #include <grpcpp/impl/codegen/server_interface.h>
29 #include <grpcpp/impl/codegen/status.h>
30
31 namespace grpc {
32
33 class CompletionQueue;
34 class ServerContext;
35 class ServerInterface;
36
37 namespace internal {
38 class Call;
39 class ServerAsyncStreamingInterface {
40  public:
41   virtual ~ServerAsyncStreamingInterface() {}
42
43   /// Request notification of the sending of initial metadata to the client.
44   /// Completion will be notified by \a tag on the associated completion
45   /// queue. This call is optional, but if it is used, it cannot be used
46   /// concurrently with or after the \a Finish method.
47   ///
48   /// \param[in] tag Tag identifying this request.
49   virtual void SendInitialMetadata(void* tag) = 0;
50
51  private:
52   friend class ::grpc::ServerInterface;
53   virtual void BindCall(Call* call) = 0;
54 };
55 }  // namespace internal
56
57 /// Desriptor of an RPC service and its various RPC methods
58 class Service {
59  public:
60   Service() : server_(nullptr) {}
61   virtual ~Service() {}
62
63   bool has_async_methods() const {
64     for (const auto& method : methods_) {
65       if (method && method->handler() == nullptr) {
66         return true;
67       }
68     }
69     return false;
70   }
71
72   bool has_synchronous_methods() const {
73     for (const auto& method : methods_) {
74       if (method &&
75           method->api_type() == internal::RpcServiceMethod::ApiType::SYNC) {
76         return true;
77       }
78     }
79     return false;
80   }
81
82   bool has_callback_methods() const {
83     for (const auto& method : methods_) {
84       if (method && (method->api_type() ==
85                          internal::RpcServiceMethod::ApiType::CALL_BACK ||
86                      method->api_type() ==
87                          internal::RpcServiceMethod::ApiType::RAW_CALL_BACK)) {
88         return true;
89       }
90     }
91     return false;
92   }
93
94   bool has_generic_methods() const {
95     for (const auto& method : methods_) {
96       if (method == nullptr) {
97         return true;
98       }
99     }
100     return false;
101   }
102
103  protected:
104   template <class Message>
105   void RequestAsyncUnary(int index, ::grpc::ServerContext* context,
106                          Message* request,
107                          internal::ServerAsyncStreamingInterface* stream,
108                          ::grpc::CompletionQueue* call_cq,
109                          ::grpc::ServerCompletionQueue* notification_cq,
110                          void* tag) {
111     // Typecast the index to size_t for indexing into a vector
112     // while preserving the API that existed before a compiler
113     // warning was first seen (grpc/grpc#11664)
114     size_t idx = static_cast<size_t>(index);
115     server_->RequestAsyncCall(methods_[idx].get(), context, stream, call_cq,
116                               notification_cq, tag, request);
117   }
118   void RequestAsyncClientStreaming(
119       int index, ::grpc::ServerContext* context,
120       internal::ServerAsyncStreamingInterface* stream,
121       ::grpc::CompletionQueue* call_cq,
122       ::grpc::ServerCompletionQueue* notification_cq, void* tag) {
123     size_t idx = static_cast<size_t>(index);
124     server_->RequestAsyncCall(methods_[idx].get(), context, stream, call_cq,
125                               notification_cq, tag);
126   }
127   template <class Message>
128   void RequestAsyncServerStreaming(
129       int index, ::grpc::ServerContext* context, Message* request,
130       internal::ServerAsyncStreamingInterface* stream,
131       ::grpc::CompletionQueue* call_cq,
132       ::grpc::ServerCompletionQueue* notification_cq, void* tag) {
133     size_t idx = static_cast<size_t>(index);
134     server_->RequestAsyncCall(methods_[idx].get(), context, stream, call_cq,
135                               notification_cq, tag, request);
136   }
137   void RequestAsyncBidiStreaming(
138       int index, ::grpc::ServerContext* context,
139       internal::ServerAsyncStreamingInterface* stream,
140       ::grpc::CompletionQueue* call_cq,
141       ::grpc::ServerCompletionQueue* notification_cq, void* tag) {
142     size_t idx = static_cast<size_t>(index);
143     server_->RequestAsyncCall(methods_[idx].get(), context, stream, call_cq,
144                               notification_cq, tag);
145   }
146
147   void AddMethod(internal::RpcServiceMethod* method) {
148     methods_.emplace_back(method);
149   }
150
151   void MarkMethodAsync(int index) {
152     // This does not have to be a hard error, however no one has approached us
153     // with a use case yet. Please file an issue if you believe you have one.
154     size_t idx = static_cast<size_t>(index);
155     GPR_CODEGEN_ASSERT(
156         methods_[idx].get() != nullptr &&
157         "Cannot mark the method as 'async' because it has already been "
158         "marked as 'generic'.");
159     methods_[idx]->SetServerApiType(internal::RpcServiceMethod::ApiType::ASYNC);
160   }
161
162   void MarkMethodRaw(int index) {
163     // This does not have to be a hard error, however no one has approached us
164     // with a use case yet. Please file an issue if you believe you have one.
165     size_t idx = static_cast<size_t>(index);
166     GPR_CODEGEN_ASSERT(methods_[idx].get() != nullptr &&
167                        "Cannot mark the method as 'raw' because it has already "
168                        "been marked as 'generic'.");
169     methods_[idx]->SetServerApiType(internal::RpcServiceMethod::ApiType::RAW);
170   }
171
172   void MarkMethodGeneric(int index) {
173     // This does not have to be a hard error, however no one has approached us
174     // with a use case yet. Please file an issue if you believe you have one.
175     size_t idx = static_cast<size_t>(index);
176     GPR_CODEGEN_ASSERT(
177         methods_[idx]->handler() != nullptr &&
178         "Cannot mark the method as 'generic' because it has already been "
179         "marked as 'async' or 'raw'.");
180     methods_[idx].reset();
181   }
182
183   void MarkMethodStreamed(int index, internal::MethodHandler* streamed_method) {
184     // This does not have to be a hard error, however no one has approached us
185     // with a use case yet. Please file an issue if you believe you have one.
186     size_t idx = static_cast<size_t>(index);
187     GPR_CODEGEN_ASSERT(methods_[idx] && methods_[idx]->handler() &&
188                        "Cannot mark an async or generic method Streamed");
189     methods_[idx]->SetHandler(streamed_method);
190
191     // From the server's point of view, streamed unary is a special
192     // case of BIDI_STREAMING that has 1 read and 1 write, in that order,
193     // and split server-side streaming is BIDI_STREAMING with 1 read and
194     // any number of writes, in that order.
195     methods_[idx]->SetMethodType(internal::RpcMethod::BIDI_STREAMING);
196   }
197
198   void MarkMethodCallback(int index, internal::MethodHandler* handler) {
199     // This does not have to be a hard error, however no one has approached us
200     // with a use case yet. Please file an issue if you believe you have one.
201     size_t idx = static_cast<size_t>(index);
202     GPR_CODEGEN_ASSERT(
203         methods_[idx].get() != nullptr &&
204         "Cannot mark the method as 'callback' because it has already been "
205         "marked as 'generic'.");
206     methods_[idx]->SetHandler(handler);
207     methods_[idx]->SetServerApiType(
208         internal::RpcServiceMethod::ApiType::CALL_BACK);
209   }
210
211   void MarkMethodRawCallback(int index, internal::MethodHandler* handler) {
212     // This does not have to be a hard error, however no one has approached us
213     // with a use case yet. Please file an issue if you believe you have one.
214     size_t idx = static_cast<size_t>(index);
215     GPR_CODEGEN_ASSERT(
216         methods_[idx].get() != nullptr &&
217         "Cannot mark the method as 'raw callback' because it has already "
218         "been marked as 'generic'.");
219     methods_[idx]->SetHandler(handler);
220     methods_[idx]->SetServerApiType(
221         internal::RpcServiceMethod::ApiType::RAW_CALL_BACK);
222   }
223
224   internal::MethodHandler* GetHandler(int index) {
225     size_t idx = static_cast<size_t>(index);
226     return methods_[idx]->handler();
227   }
228
229  private:
230   friend class Server;
231   friend class ServerInterface;
232   ServerInterface* server_;
233   std::vector<std::unique_ptr<internal::RpcServiceMethod>> methods_;
234 };
235
236 }  // namespace grpc
237
238 #endif  // GRPCPP_IMPL_CODEGEN_SERVICE_TYPE_H