• 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_CODEGEN_SERVICE_TYPE_H
20 #define GRPCPP_IMPL_CODEGEN_SERVICE_TYPE_H
21 
22 #include <grpcpp/impl/codegen/config.h>
23 #include <grpcpp/impl/codegen/core_codegen_interface.h>
24 #include <grpcpp/impl/codegen/rpc_service_method.h>
25 #include <grpcpp/impl/codegen/serialization_traits.h>
26 #include <grpcpp/impl/codegen/server_interface.h>
27 #include <grpcpp/impl/codegen/status.h>
28 
29 namespace grpc {
30 
31 class CompletionQueue;
32 class Server;
33 class ServerInterface;
34 class ServerCompletionQueue;
35 class ServerContext;
36 
37 namespace internal {
38 class Call;
39 class ServerAsyncStreamingInterface {
40  public:
~ServerAsyncStreamingInterface()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:
Service()60   Service() : server_(nullptr) {}
~Service()61   virtual ~Service() {}
62 
has_async_methods()63   bool has_async_methods() const {
64     for (auto it = methods_.begin(); it != methods_.end(); ++it) {
65       if (*it && (*it)->handler() == nullptr) {
66         return true;
67       }
68     }
69     return false;
70   }
71 
has_synchronous_methods()72   bool has_synchronous_methods() const {
73     for (auto it = methods_.begin(); it != methods_.end(); ++it) {
74       if (*it && (*it)->handler() != nullptr) {
75         return true;
76       }
77     }
78     return false;
79   }
80 
has_generic_methods()81   bool has_generic_methods() const {
82     for (auto it = methods_.begin(); it != methods_.end(); ++it) {
83       if (it->get() == nullptr) {
84         return true;
85       }
86     }
87     return false;
88   }
89 
90  protected:
91   template <class Message>
RequestAsyncUnary(int index,ServerContext * context,Message * request,internal::ServerAsyncStreamingInterface * stream,CompletionQueue * call_cq,ServerCompletionQueue * notification_cq,void * tag)92   void RequestAsyncUnary(int index, ServerContext* context, Message* request,
93                          internal::ServerAsyncStreamingInterface* stream,
94                          CompletionQueue* call_cq,
95                          ServerCompletionQueue* notification_cq, void* tag) {
96     // Typecast the index to size_t for indexing into a vector
97     // while preserving the API that existed before a compiler
98     // warning was first seen (grpc/grpc#11664)
99     size_t idx = static_cast<size_t>(index);
100     server_->RequestAsyncCall(methods_[idx].get(), context, stream, call_cq,
101                               notification_cq, tag, request);
102   }
RequestAsyncClientStreaming(int index,ServerContext * context,internal::ServerAsyncStreamingInterface * stream,CompletionQueue * call_cq,ServerCompletionQueue * notification_cq,void * tag)103   void RequestAsyncClientStreaming(
104       int index, ServerContext* context,
105       internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
106       ServerCompletionQueue* notification_cq, void* tag) {
107     size_t idx = static_cast<size_t>(index);
108     server_->RequestAsyncCall(methods_[idx].get(), context, stream, call_cq,
109                               notification_cq, tag);
110   }
111   template <class Message>
RequestAsyncServerStreaming(int index,ServerContext * context,Message * request,internal::ServerAsyncStreamingInterface * stream,CompletionQueue * call_cq,ServerCompletionQueue * notification_cq,void * tag)112   void RequestAsyncServerStreaming(
113       int index, ServerContext* context, Message* request,
114       internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
115       ServerCompletionQueue* notification_cq, void* tag) {
116     size_t idx = static_cast<size_t>(index);
117     server_->RequestAsyncCall(methods_[idx].get(), context, stream, call_cq,
118                               notification_cq, tag, request);
119   }
RequestAsyncBidiStreaming(int index,ServerContext * context,internal::ServerAsyncStreamingInterface * stream,CompletionQueue * call_cq,ServerCompletionQueue * notification_cq,void * tag)120   void RequestAsyncBidiStreaming(
121       int index, ServerContext* context,
122       internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
123       ServerCompletionQueue* notification_cq, void* tag) {
124     size_t idx = static_cast<size_t>(index);
125     server_->RequestAsyncCall(methods_[idx].get(), context, stream, call_cq,
126                               notification_cq, tag);
127   }
128 
AddMethod(internal::RpcServiceMethod * method)129   void AddMethod(internal::RpcServiceMethod* method) {
130     methods_.emplace_back(method);
131   }
132 
MarkMethodAsync(int index)133   void MarkMethodAsync(int index) {
134     // This does not have to be a hard error, however no one has approached us
135     // with a use case yet. Please file an issue if you believe you have one.
136     size_t idx = static_cast<size_t>(index);
137     GPR_CODEGEN_ASSERT(
138         methods_[idx].get() != nullptr &&
139         "Cannot mark the method as 'async' because it has already been "
140         "marked as 'generic'.");
141     methods_[idx]->SetServerAsyncType(
142         internal::RpcServiceMethod::AsyncType::ASYNC);
143   }
144 
MarkMethodRaw(int index)145   void MarkMethodRaw(int index) {
146     // This does not have to be a hard error, however no one has approached us
147     // with a use case yet. Please file an issue if you believe you have one.
148     size_t idx = static_cast<size_t>(index);
149     GPR_CODEGEN_ASSERT(methods_[idx].get() != nullptr &&
150                        "Cannot mark the method as 'raw' because it has already "
151                        "been marked as 'generic'.");
152     methods_[idx]->SetServerAsyncType(
153         internal::RpcServiceMethod::AsyncType::RAW);
154   }
155 
MarkMethodGeneric(int index)156   void MarkMethodGeneric(int index) {
157     // This does not have to be a hard error, however no one has approached us
158     // with a use case yet. Please file an issue if you believe you have one.
159     size_t idx = static_cast<size_t>(index);
160     GPR_CODEGEN_ASSERT(
161         methods_[idx]->handler() != nullptr &&
162         "Cannot mark the method as 'generic' because it has already been "
163         "marked as 'async' or 'raw'.");
164     methods_[idx].reset();
165   }
166 
MarkMethodStreamed(int index,internal::MethodHandler * streamed_method)167   void MarkMethodStreamed(int index, internal::MethodHandler* streamed_method) {
168     // This does not have to be a hard error, however no one has approached us
169     // with a use case yet. Please file an issue if you believe you have one.
170     size_t idx = static_cast<size_t>(index);
171     GPR_CODEGEN_ASSERT(methods_[idx] && methods_[idx]->handler() &&
172                        "Cannot mark an async or generic method Streamed");
173     methods_[idx]->SetHandler(streamed_method);
174 
175     // From the server's point of view, streamed unary is a special
176     // case of BIDI_STREAMING that has 1 read and 1 write, in that order,
177     // and split server-side streaming is BIDI_STREAMING with 1 read and
178     // any number of writes, in that order.
179     methods_[idx]->SetMethodType(internal::RpcMethod::BIDI_STREAMING);
180   }
181 
182  private:
183   friend class Server;
184   friend class ServerInterface;
185   ServerInterface* server_;
186   std::vector<std::unique_ptr<internal::RpcServiceMethod>> methods_;
187 };
188 
189 }  // namespace grpc
190 
191 #endif  // GRPCPP_IMPL_CODEGEN_SERVICE_TYPE_H
192