• 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_GENERIC_GENERIC_STUB_H
20 #define GRPCPP_GENERIC_GENERIC_STUB_H
21 
22 #include <functional>
23 
24 #include <grpcpp/client_context.h>
25 #include <grpcpp/impl/rpc_method.h>
26 #include <grpcpp/support/async_stream.h>
27 #include <grpcpp/support/async_unary_call.h>
28 #include <grpcpp/support/byte_buffer.h>
29 #include <grpcpp/support/client_callback.h>
30 #include <grpcpp/support/status.h>
31 
32 namespace grpc {
33 
34 class CompletionQueue;
35 
36 typedef ClientAsyncReaderWriter<ByteBuffer, ByteBuffer>
37     GenericClientAsyncReaderWriter;
38 typedef ClientAsyncResponseReader<ByteBuffer> GenericClientAsyncResponseReader;
39 
40 /// Generic stubs provide a type-unaware interface to call gRPC methods
41 /// by name. In practice, the Request and Response types should be basic
42 /// types like grpc::ByteBuffer or proto::MessageLite (the base protobuf).
43 template <class RequestType, class ResponseType>
44 class TemplatedGenericStub final {
45  public:
TemplatedGenericStub(std::shared_ptr<grpc::ChannelInterface> channel)46   explicit TemplatedGenericStub(std::shared_ptr<grpc::ChannelInterface> channel)
47       : channel_(channel) {}
48 
49   /// Setup a call to a named method \a method using \a context, but don't
50   /// start it. Let it be started explicitly with StartCall and a tag.
51   /// The return value only indicates whether or not registration of the call
52   /// succeeded (i.e. the call won't proceed if the return value is nullptr).
53   std::unique_ptr<ClientAsyncReaderWriter<RequestType, ResponseType>>
PrepareCall(ClientContext * context,const std::string & method,::grpc::CompletionQueue * cq)54   PrepareCall(ClientContext* context, const std::string& method,
55               ::grpc::CompletionQueue* cq) {
56     return CallInternal(channel_.get(), context, method, cq, false, nullptr);
57   }
58 
59   /// Setup a unary call to a named method \a method using \a context, and don't
60   /// start it. Let it be started explicitly with StartCall.
61   /// The return value only indicates whether or not registration of the call
62   /// succeeded (i.e. the call won't proceed if the return value is nullptr).
PrepareUnaryCall(ClientContext * context,const std::string & method,const RequestType & request,::grpc::CompletionQueue * cq)63   std::unique_ptr<ClientAsyncResponseReader<ResponseType>> PrepareUnaryCall(
64       ClientContext* context, const std::string& method,
65       const RequestType& request, ::grpc::CompletionQueue* cq) {
66     return std::unique_ptr<ClientAsyncResponseReader<ResponseType>>(
67         internal::ClientAsyncResponseReaderHelper::Create<ResponseType>(
68             channel_.get(), cq,
69             grpc::internal::RpcMethod(method.c_str(),
70                                       grpc::internal::RpcMethod::NORMAL_RPC),
71             context, request));
72   }
73 
74   /// DEPRECATED for multi-threaded use
75   /// Begin a call to a named method \a method using \a context.
76   /// A tag \a tag will be delivered to \a cq when the call has been started
77   /// (i.e, initial metadata has been sent).
78   /// The return value only indicates whether or not registration of the call
79   /// succeeded (i.e. the call won't proceed if the return value is nullptr).
Call(ClientContext * context,const std::string & method,::grpc::CompletionQueue * cq,void * tag)80   std::unique_ptr<ClientAsyncReaderWriter<RequestType, ResponseType>> Call(
81       ClientContext* context, const std::string& method,
82       ::grpc::CompletionQueue* cq, void* tag) {
83     return CallInternal(channel_.get(), context, method, cq, true, tag);
84   }
85 
86 #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
87   /// Setup and start a unary call to a named method \a method using
88   /// \a context and specifying the \a request and \a response buffers.
UnaryCall(ClientContext * context,const std::string & method,const RequestType * request,ResponseType * response,std::function<void (grpc::Status)> on_completion)89   void UnaryCall(ClientContext* context, const std::string& method,
90                  const RequestType* request, ResponseType* response,
91                  std::function<void(grpc::Status)> on_completion) {
92     UnaryCallInternal(context, method, request, response,
93                       std::move(on_completion));
94   }
95 
96   /// Setup a unary call to a named method \a method using
97   /// \a context and specifying the \a request and \a response buffers.
98   /// Like any other reactor-based RPC, it will not be activated until
99   /// StartCall is invoked on its reactor.
PrepareUnaryCall(ClientContext * context,const std::string & method,const RequestType * request,ResponseType * response,ClientUnaryReactor * reactor)100   void PrepareUnaryCall(ClientContext* context, const std::string& method,
101                         const RequestType* request, ResponseType* response,
102                         ClientUnaryReactor* reactor) {
103     PrepareUnaryCallInternal(context, method, request, response, reactor);
104   }
105 
106   /// Setup a call to a named method \a method using \a context and tied to
107   /// \a reactor . Like any other bidi streaming RPC, it will not be activated
108   /// until StartCall is invoked on its reactor.
PrepareBidiStreamingCall(ClientContext * context,const std::string & method,ClientBidiReactor<RequestType,ResponseType> * reactor)109   void PrepareBidiStreamingCall(
110       ClientContext* context, const std::string& method,
111       ClientBidiReactor<RequestType, ResponseType>* reactor) {
112     PrepareBidiStreamingCallInternal(context, method, reactor);
113   }
114 #endif
115 
116   /// NOTE: class experimental_type is not part of the public API of this class
117   /// TODO(vjpai): Move these contents to the public API of GenericStub when
118   ///              they are no longer experimental
119   class experimental_type {
120    public:
experimental_type(TemplatedGenericStub * stub)121     explicit experimental_type(TemplatedGenericStub* stub) : stub_(stub) {}
122 
123     /// Setup and start a unary call to a named method \a method using
124     /// \a context and specifying the \a request and \a response buffers.
UnaryCall(ClientContext * context,const std::string & method,const RequestType * request,ResponseType * response,std::function<void (grpc::Status)> on_completion)125     void UnaryCall(ClientContext* context, const std::string& method,
126                    const RequestType* request, ResponseType* response,
127                    std::function<void(grpc::Status)> on_completion) {
128       stub_->UnaryCallInternal(context, method, request, response,
129                                std::move(on_completion));
130     }
131 
132     /// Setup a unary call to a named method \a method using
133     /// \a context and specifying the \a request and \a response buffers.
134     /// Like any other reactor-based RPC, it will not be activated until
135     /// StartCall is invoked on its reactor.
PrepareUnaryCall(ClientContext * context,const std::string & method,const RequestType * request,ResponseType * response,ClientUnaryReactor * reactor)136     void PrepareUnaryCall(ClientContext* context, const std::string& method,
137                           const RequestType* request, ResponseType* response,
138                           ClientUnaryReactor* reactor) {
139       stub_->PrepareUnaryCallInternal(context, method, request, response,
140                                       reactor);
141     }
142 
143     /// Setup a call to a named method \a method using \a context and tied to
144     /// \a reactor . Like any other bidi streaming RPC, it will not be activated
145     /// until StartCall is invoked on its reactor.
PrepareBidiStreamingCall(ClientContext * context,const std::string & method,ClientBidiReactor<RequestType,ResponseType> * reactor)146     void PrepareBidiStreamingCall(
147         ClientContext* context, const std::string& method,
148         ClientBidiReactor<RequestType, ResponseType>* reactor) {
149       stub_->PrepareBidiStreamingCallInternal(context, method, reactor);
150     }
151 
152    private:
153     TemplatedGenericStub* stub_;
154   };
155 
156   /// NOTE: The function experimental() is not stable public API. It is a view
157   /// to the experimental components of this class. It may be changed or removed
158   /// at any time.
experimental()159   experimental_type experimental() { return experimental_type(this); }
160 
161  private:
162   std::shared_ptr<grpc::ChannelInterface> channel_;
163 
UnaryCallInternal(ClientContext * context,const std::string & method,const RequestType * request,ResponseType * response,std::function<void (grpc::Status)> on_completion)164   void UnaryCallInternal(ClientContext* context, const std::string& method,
165                          const RequestType* request, ResponseType* response,
166                          std::function<void(grpc::Status)> on_completion) {
167     internal::CallbackUnaryCall(
168         channel_.get(),
169         grpc::internal::RpcMethod(method.c_str(),
170                                   grpc::internal::RpcMethod::NORMAL_RPC),
171         context, request, response, std::move(on_completion));
172   }
173 
PrepareUnaryCallInternal(ClientContext * context,const std::string & method,const RequestType * request,ResponseType * response,ClientUnaryReactor * reactor)174   void PrepareUnaryCallInternal(ClientContext* context,
175                                 const std::string& method,
176                                 const RequestType* request,
177                                 ResponseType* response,
178                                 ClientUnaryReactor* reactor) {
179     internal::ClientCallbackUnaryFactory::Create<RequestType, ResponseType>(
180         channel_.get(),
181         grpc::internal::RpcMethod(method.c_str(),
182                                   grpc::internal::RpcMethod::NORMAL_RPC),
183         context, request, response, reactor);
184   }
185 
PrepareBidiStreamingCallInternal(ClientContext * context,const std::string & method,ClientBidiReactor<RequestType,ResponseType> * reactor)186   void PrepareBidiStreamingCallInternal(
187       ClientContext* context, const std::string& method,
188       ClientBidiReactor<RequestType, ResponseType>* reactor) {
189     internal::ClientCallbackReaderWriterFactory<RequestType, ResponseType>::
190         Create(channel_.get(),
191                grpc::internal::RpcMethod(
192                    method.c_str(), grpc::internal::RpcMethod::BIDI_STREAMING),
193                context, reactor);
194   }
195 
196   std::unique_ptr<ClientAsyncReaderWriter<RequestType, ResponseType>>
CallInternal(grpc::ChannelInterface * channel,ClientContext * context,const std::string & method,::grpc::CompletionQueue * cq,bool start,void * tag)197   CallInternal(grpc::ChannelInterface* channel, ClientContext* context,
198                const std::string& method, ::grpc::CompletionQueue* cq,
199                bool start, void* tag) {
200     return std::unique_ptr<ClientAsyncReaderWriter<RequestType, ResponseType>>(
201         internal::ClientAsyncReaderWriterFactory<RequestType, ResponseType>::
202             Create(
203                 channel, cq,
204                 grpc::internal::RpcMethod(
205                     method.c_str(), grpc::internal::RpcMethod::BIDI_STREAMING),
206                 context, start, tag));
207   }
208 };
209 
210 typedef TemplatedGenericStub<grpc::ByteBuffer, grpc::ByteBuffer> GenericStub;
211 
212 }  // namespace grpc
213 
214 #endif  // GRPCPP_GENERIC_GENERIC_STUB_H
215