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