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