3 * Copyright 2015 gRPC authors.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #ifndef GRPCPP_IMPL_CODEGEN_SERVICE_TYPE_H
20 #define GRPCPP_IMPL_CODEGEN_SERVICE_TYPE_H
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>
31 class CompletionQueue;
33 class ServerInterface;
34 class ServerCompletionQueue;
39 class ServerAsyncStreamingInterface {
41 virtual ~ServerAsyncStreamingInterface() {}
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.
48 /// \param[in] tag Tag identifying this request.
49 virtual void SendInitialMetadata(void* tag) = 0;
52 friend class ::grpc::ServerInterface;
53 virtual void BindCall(Call* call) = 0;
55 } // namespace internal
57 /// Desriptor of an RPC service and its various RPC methods
60 Service() : server_(nullptr) {}
63 bool has_async_methods() const {
64 for (auto it = methods_.begin(); it != methods_.end(); ++it) {
65 if (*it && (*it)->handler() == nullptr) {
72 bool has_synchronous_methods() const {
73 for (auto it = methods_.begin(); it != methods_.end(); ++it) {
75 (*it)->api_type() == internal::RpcServiceMethod::ApiType::SYNC) {
82 bool has_callback_methods() const {
83 for (auto it = methods_.begin(); it != methods_.end(); ++it) {
84 if (*it && ((*it)->api_type() ==
85 internal::RpcServiceMethod::ApiType::CALL_BACK ||
87 internal::RpcServiceMethod::ApiType::RAW_CALL_BACK)) {
94 bool has_generic_methods() const {
95 for (auto it = methods_.begin(); it != methods_.end(); ++it) {
96 if (it->get() == nullptr) {
104 // TODO(vjpai): Promote experimental contents once callback API is accepted
105 class experimental_type {
107 explicit experimental_type(Service* service) : service_(service) {}
109 void MarkMethodCallback(int index, internal::MethodHandler* handler) {
110 // This does not have to be a hard error, however no one has approached us
111 // with a use case yet. Please file an issue if you believe you have one.
112 size_t idx = static_cast<size_t>(index);
114 service_->methods_[idx].get() != nullptr &&
115 "Cannot mark the method as 'callback' because it has already been "
116 "marked as 'generic'.");
117 service_->methods_[idx]->SetHandler(handler);
118 service_->methods_[idx]->SetServerApiType(
119 internal::RpcServiceMethod::ApiType::CALL_BACK);
122 void MarkMethodRawCallback(int index, internal::MethodHandler* handler) {
123 // This does not have to be a hard error, however no one has approached us
124 // with a use case yet. Please file an issue if you believe you have one.
125 size_t idx = static_cast<size_t>(index);
127 service_->methods_[idx].get() != nullptr &&
128 "Cannot mark the method as 'raw callback' because it has already "
129 "been marked as 'generic'.");
130 service_->methods_[idx]->SetHandler(handler);
131 service_->methods_[idx]->SetServerApiType(
132 internal::RpcServiceMethod::ApiType::RAW_CALL_BACK);
139 experimental_type experimental() { return experimental_type(this); }
141 template <class Message>
142 void RequestAsyncUnary(int index, ServerContext* context, Message* request,
143 internal::ServerAsyncStreamingInterface* stream,
144 CompletionQueue* call_cq,
145 ServerCompletionQueue* notification_cq, void* tag) {
146 // Typecast the index to size_t for indexing into a vector
147 // while preserving the API that existed before a compiler
148 // warning was first seen (grpc/grpc#11664)
149 size_t idx = static_cast<size_t>(index);
150 server_->RequestAsyncCall(methods_[idx].get(), context, stream, call_cq,
151 notification_cq, tag, request);
153 void RequestAsyncClientStreaming(
154 int index, ServerContext* context,
155 internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
156 ServerCompletionQueue* notification_cq, void* tag) {
157 size_t idx = static_cast<size_t>(index);
158 server_->RequestAsyncCall(methods_[idx].get(), context, stream, call_cq,
159 notification_cq, tag);
161 template <class Message>
162 void RequestAsyncServerStreaming(
163 int index, ServerContext* context, Message* request,
164 internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
165 ServerCompletionQueue* notification_cq, void* tag) {
166 size_t idx = static_cast<size_t>(index);
167 server_->RequestAsyncCall(methods_[idx].get(), context, stream, call_cq,
168 notification_cq, tag, request);
170 void RequestAsyncBidiStreaming(
171 int index, ServerContext* context,
172 internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
173 ServerCompletionQueue* notification_cq, void* tag) {
174 size_t idx = static_cast<size_t>(index);
175 server_->RequestAsyncCall(methods_[idx].get(), context, stream, call_cq,
176 notification_cq, tag);
179 void AddMethod(internal::RpcServiceMethod* method) {
180 methods_.emplace_back(method);
183 void MarkMethodAsync(int index) {
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);
188 methods_[idx].get() != nullptr &&
189 "Cannot mark the method as 'async' because it has already been "
190 "marked as 'generic'.");
191 methods_[idx]->SetServerApiType(internal::RpcServiceMethod::ApiType::ASYNC);
194 void MarkMethodRaw(int index) {
195 // This does not have to be a hard error, however no one has approached us
196 // with a use case yet. Please file an issue if you believe you have one.
197 size_t idx = static_cast<size_t>(index);
198 GPR_CODEGEN_ASSERT(methods_[idx].get() != nullptr &&
199 "Cannot mark the method as 'raw' because it has already "
200 "been marked as 'generic'.");
201 methods_[idx]->SetServerApiType(internal::RpcServiceMethod::ApiType::RAW);
204 void MarkMethodGeneric(int index) {
205 // This does not have to be a hard error, however no one has approached us
206 // with a use case yet. Please file an issue if you believe you have one.
207 size_t idx = static_cast<size_t>(index);
209 methods_[idx]->handler() != nullptr &&
210 "Cannot mark the method as 'generic' because it has already been "
211 "marked as 'async' or 'raw'.");
212 methods_[idx].reset();
215 void MarkMethodStreamed(int index, internal::MethodHandler* streamed_method) {
216 // This does not have to be a hard error, however no one has approached us
217 // with a use case yet. Please file an issue if you believe you have one.
218 size_t idx = static_cast<size_t>(index);
219 GPR_CODEGEN_ASSERT(methods_[idx] && methods_[idx]->handler() &&
220 "Cannot mark an async or generic method Streamed");
221 methods_[idx]->SetHandler(streamed_method);
223 // From the server's point of view, streamed unary is a special
224 // case of BIDI_STREAMING that has 1 read and 1 write, in that order,
225 // and split server-side streaming is BIDI_STREAMING with 1 read and
226 // any number of writes, in that order.
227 methods_[idx]->SetMethodType(internal::RpcMethod::BIDI_STREAMING);
232 friend class ServerInterface;
233 ServerInterface* server_;
234 std::vector<std::unique_ptr<internal::RpcServiceMethod>> methods_;
239 #endif // GRPCPP_IMPL_CODEGEN_SERVICE_TYPE_H