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